{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "OulJtk4XKB3i"
   },
   "source": [
    "#  РАЗВЕДОЧНЫЙ АНАЛИЗ ДАННЫХ"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Задачи, которые ставятся перед аналитиками, достаточно разнообразны. Однако всё начинается с данных - с \"сырых\" данных.\n",
    "\n",
    "К сожалению, на практике данные в \"сыром\" виде обычно малопригодны для анализа. Процесс подготовки и очистки данных (препроцессинг, англ. data preparation, pre-processing, data cleaning) может быть весьма трудоёмким и по времени занимать больше, чем собственно построение и валидация моделей на основе данных. \n",
    "\n",
    "В результате получаем данные в удобном для анализа формате, как правило, табличном. Таблица (или датафрейм) имеет структуру \"объекты-признаки\": строки соответствуют отдельным сущностям (объектам, примерам, экземплярам), а столбцы - атрибутам этих сущностей (признакам).\n",
    "\n",
    "Обычно работа аналитика при решении задач анализа данных начинается с разведочного анализа данных.\n",
    "\n",
    "**Exploratory data analysis (EDA)** - это подход к анализу наборов данных для обобщения их основных характеристик, часто с использованием статистической графики и других методов визуализации данных."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Исследование основных характеристик датасета"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Частично с этими функциями мы встречались на прошлых занятиях, давайте еще раз повторим."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Текстовое описание набора данных"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Затопление \"Титаника\" - одно из самых печально известных кораблекрушений в истории.\n",
    "\n",
    "15 апреля 1912 года, во время своего первого рейса, широко известный “непотопляемый” корабль \"Титаник\" затонул после столкновения с айсбергом. К сожалению, на борту не хватило спасательных шлюпок для всех, что привело к гибели 1502 из 2224 пассажиров и членов экипажа.\n",
    "\n",
    "Хотя в выживании был определенный элемент удачи, похоже, что у некоторых групп людей было больше шансов выжить, чем у других.\n",
    "\n",
    "Используя данные о пассажирах (например, имя, возраст, пол, социально-экономический класс и т. д.) необходимо узнать \"У каких людей было больше шансов выжить?”."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Каждая строчка набора данных содержит следующие поля:\n",
    "\n",
    "- `PassengerId` — номер пассажира;\n",
    "\n",
    "- `Survived` — выжил данный пассажир или нет (0 для умерших, 1 для выживших);\n",
    "\n",
    "- `Pclass` — класс пассажира (1 — высший, 2 — средний, 3 — низший);\n",
    "\n",
    "- `Name` — имя;\n",
    "\n",
    "- `Sex` — пол;\n",
    "\n",
    "- `Age` — возраст;\n",
    "\n",
    "- `SibSp` — количество братьев, сестер, сводных братьев, сводных сестер, супругов на борту титаника;\n",
    "\n",
    "- `Parch` — количество родителей, детей (в том числе приемных) на борту титаника;\n",
    "\n",
    "- `Ticket` — номер билета;\n",
    "\n",
    "- `Fare` — плата за проезд;\n",
    "\n",
    "- `Cabin` — каюта;\n",
    "\n",
    "- `Embarked` — порт посадки (C — Шербур; Q — Квинстаун; S — Саутгемптон)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Загрузка датасета"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Загрузим файлы датасета c помощью библиотеки [`Pandas`](https://pandas.pydata.org/)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.read_csv(\"titanic.csv\", sep=\";\")\n",
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Исследование внешних признаков датасета"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(df.shape)\n",
    "print(f'Всего строк: {df.shape[0]}')\n",
    "print(f'Всего колонок: {df.shape[1]}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.columns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.dtypes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- значение Age не задано для большого количества записей. Из 891 строк, возраст Age задан лишь для 714 записей.\n",
    "- каюты Cabin пропущены для большого количества записей. Только 204 из 891 записей содержат Cabin значения."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for col in df.columns:\n",
    "    print('{} - {}'.format(col, df[df[col].isnull()].shape[0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Описательные статистики"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[Кванти́ль](https://ru.wikipedia.org/wiki/%D0%9A%D0%B2%D0%B0%D0%BD%D1%82%D0%B8%D0%BB%D1%8C) — значение, которое заданная случайная величина не превышает с фиксированной вероятностью. Если вероятность задана в процентах, то квантиль называется процентилем или перцентилем:\n",
    "\n",
    "$$P(X\\le x_\\alpha)\\le\\alpha$$\n",
    "\n",
    "Основные характеристики датасета можно получить с помощью функции [`pandas.DataFrame.describe`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.describe.html). Она отобразит различные величины, такие как количество, среднее, среднеквадратичное отклонение и т.д. для численных типов данных. Это может быть полезным для понимания распределения значений по датасету и статистики, особенно когда нет возможности просмотреть все записи в виду огромного их количества.\n",
    "\n",
    "Например, фраза \"90-й процентиль массы тела у новорожденных мальчиков составляет 4 кг\" означает, что 90 % мальчиков рождаются с весом меньше, либо равным 4 кг, а 10 % мальчиков рождаются с весом больше 4 кг.\n",
    "\n",
    "Пусть $X_1, \\ldots X_n$ — выборка.\n",
    "\n",
    "В итоге получаем следующие стоки:\n",
    "\n",
    "* `count` - количество non-NA/null наблюдений.\n",
    "* `mean` - средняя значений в колонке $\\overline{X}  = \\frac1n \\sum\\limits_{i=1}^n X_i$ .\n",
    "* `min` - минимальное значение в колонке $min(X_1, \\ldots X_n)$.\n",
    "* `25%` - 25-й перцентиль (0,25-квантиль называется первым (или нижним) кварти́лем (от лат. quarta — четверть)).\n",
    "* `50%` - 50-й перцентиль (0,5-квантиль называется медианой (от лат. mediāna — середина) или вторым кварти́лем) $P(X\\le x_{0.5})\\le 0.5$.\n",
    "* `75%` - 75-й перцентиль (0,75-квантиль называется третьим (или верхним) кварти́лем).\n",
    "* `max` - максимальное значение в колонке $max(X_1, \\ldots X_n)$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.describe()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Если необходимо отобразить статистики объектного типа можно воспользоваться атрибутом `.describe(include = ['O'])`. Это нужно для нечисловых данных, когда нельзя просто посчитать максимумы/среднее/и пр. для данных. Мы можем отнести такие данные к категориальному виду."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.describe(include=['O'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Что здесь можно увидеть интересного:\n",
    "\n",
    "- видно, что сущесвуют дубликаты номеров билетов Ticket и переиспользуются каюты Cabins (уникальных записей (unique) меньше, чем общего количества). \n",
    "- самый большой порядок дубликата билета - \"347082\". Он повторился 7 раз. Две каюты занимают по 4 человека. Они используют каюты \"B96 B98\".\n",
    "- 644 человека отбыли из порта \"S\".\n",
    "- из 891 записей, 574 были мужчины (male)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Давайте проанализируем зависимости между разными данными по отношению к столбцу выживших(Survival), чтобы понять как разные признаки влияют на спасение. Чуть позже мы построим визуализации для более наглядного представления результатов."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1. Правда ли, что пассажиры более высокого класса имеют большие шансы на спасение?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Посмотрим на распределение классов"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['Pclass'].value_counts()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Произведем агрегирование данных, общая процедура для работы функции `groupby` такая: разделение-применение-объединение."
   ]
  },
  {
   "attachments": {
    "2023-04-29_17-07-39.png": {
     "image/png": "iVBORw0KGgoAAAANSUhEUgAAAa0AAAERCAIAAABHPG9uAAAgAElEQVR4nO2dB1QTS/+w/+d8l17svdE7CnYBvWLv2AV7BUXsotgVGxZAryAKKiooKEWliFwREVGaAlKkKEpTOoQWSuDy/ZJV4E1zU0gh85w5nCWZzM7O7DyZ2ezO/F8rAoFAiDb/x+8MIBAIBJ9BHkQgEKIO8iACgRB1kAcRCISogzyIYJ2Wiqx3oQE+j3yfhMZ+ITTzOzsc0fAl/IGH5/224Bn4sZTfeeImzcUffP85c+rk5bvh34ltrxLzE/719XC5fOFhUiMfMycwIA8iWIfgtUFVQXkYJSiPXn0zuYHfOWKfjsdCDsozziXwO09co6X4hc0k1V+HpqC/5nYmCcyY93TPRDXKK5ozz0QLcd1xD+RBBOuQ3aFiciE6O/n5ORMdVd2tzwj8zhLbUI5lxj6PoKCg4CfnV2iodCEPklIvz1ZXHLPBOTIt6dnh6Wqqo/aEVjW8PzZJb/7JwMTcsjrh7spzEeRBBOtQ3LHsRk5za0uhu6mG8txLT+8f2bRswZTJM5bs985oICY/OLx+4azJxiYW1+PJiiSl3LPeZm6+FcLWs8EFLa0tlR/c9qyYZjxr8Q7XuEr4v+i53XYsgsUhr3QSdQRCuOO27deh79KYdHef5YXnRYRXDlaWzjHQmWnMfHT02KMsUktl/O3dy2ZNnrFsx814SJLlY4HRYtBOXbIHIfE9Dg8fHlw2Y/KcLY5RZS2tNLsre21vaXnYm9y/gsyH2FlZnPT/3kydB5pss3FcNGWFm+Yc18Uq6rMd0iiZLH24TkfJ4FhEouOckVudfa8c2Ln/pHtsSWWEgyUUu+UJv+9tVqTZIyn53kELSu2YbzsfVNCebcil97ET3ll8PlKOQR5EsE67Oxo+nJmiprLCNfDiqkVrLbevnaGjNHrXi8qo86tWbNm+cspwBa2tflWtrQ2hu/TUh0+cPVFPXXnetUxS7WsbIyX1v5dtWTVJU322fSqJlOE4V11j3PTJo7WgrUY1UEVILri7SkXNwo/YWv/v/pGqi52yiu6aaahu8Sc2f7+3Wk950qmYioiDBmpqRqZbTKdoqMy7nMr6sbR58AM5cUXV8XM3rJuqq6I82zG1kXp37/PumaoqK47d97wSJGE/S0VZafrFROo8tBRRZfsr68fVSFNWuKup4d1xA+XhWwOwy4KNH89NV1LbcP/p/lE6+rraYyaMHa6oOMr83kObeVNGqqlPs2u7Uki7x4aQ3aOUR0yeMWmUsorJ1czG38cFuVyrq2J8IobPR8oxyIMI1iG7Q2msieV+c5MJKoojTG9/+9WVqH1irqFhereI8lXemHVtseqYA2HQDAmP1msY2ERU/btvjAp4sPb9UUN1wyPv6lvrgqz01Tb51TR+PDNF29Q9P8Fulgp4sJoqgk82tCLVVf98SP5wx2J4eyvyy/bZOlJRWWnSqbcRJwxVJh2JamitC7YarrXRh5VjoedBFdO7P1pIyZfnKKtvflRJvTuyB9V0tLS0FzknPN9roKWtozz9Yhx1Hih26JjtzywfV0wNTVnhrqaGcJsxyiN3vcCuAJLSHOYrq652u2+pqai3wbuwuSps/zg1XatgYkP08YnqE8ydvLz9/k0uJTXQ7pHgvV577KE3BLLC2j3ok+1nPkplmPJvD/LvSDkGeRDBOpTfFrSGj5tkPG/1bue3hc2k3OCza6Yb6GpqKilorvYsg8HPpTnaSgoak49EwPiGlGo/Ux3aT+0vD1YHbtVWVlTVUtfQVlVR0TB/WtcQbj1mhMWzqkTMg5VUEfy/Qytq+ylD5VcrUlt9cKfh+LkLJqlMOvXGf7uWgqqKura6hqayoo75E1aOhZ4HyV2V1pbi+2ug9br/+Em1O7IHNWetXmWkYjhriu50c/PZatMvxlDngWKHjtlOZfm4Ygg0ZYW7mhrjz05W1lznVYH9F31ispLmVm+/nToq8+0/k1qb824uU1dd51VJ9qCaosZIfV2NYSrGR0J9qPdISr00S2suuf46eFB9rfXOSaPnLTRU/e1B/h0pxyAPIlinozvI1Dzfoa8+1Sb481evzVqaG31qW1sq0yMCH9iuGK46zz6tpdhzvYbenud1Db/7gy/3jlKfcS76RzFQUlLV0FJ411Rjqm1c3S8PVlFFIJKbmcriU0+Dn15apfurN6GpojV81OrbT05NhVYU+Xz/SJXZZ399opSA+1dQph4kpTsuUNba6l9FvTuyBzWmn3nmaqqtorPm7gu7WeDBWOo8tFBn+zPLxxVTTV1WLNRT2eMNWqqjd4VQLtFmXpmnrjzbPuGd7SQwV3RjK+mz/Rz13/1BDfK4uPKpha769HO3dlPVTvHDNZqjdobU1XfwoKqqrtbotW5PTk9u8yAfj5RTkAcRrEPlQeg1mamqTd5z389xwxgl8GDl11CPB4GhT+xWDlcxPur9ZN9cHWWjzWevXNk7T1dp/PrLoXF3VmorT9p+E+K4XvGOj7u3bYaG3o6AqsZfHiT+uNsxQmo99eUnSm9imPYKl4y6+NMUMX2/Z6ahPnGbW2Dos5uOj1Nw3xXHyIPKMw97B7hZ/q2uttQ1u4lmdxQPnv1YFedkfTW6KukC2YMfqfNAc9Usi+Xjiqmn+ggrt/u1FPtsGamgYrDc5sIp85laippzr3wmVYXsHKU+dpOT7+09xqrapnfyminjYv2lh+yOrBqrrGl6++P/1E7iJ/99CzRU/t5w7h+HfSaayoZr7P/9eAc6d8OXumTWQZdTld71QR4fKacgDyJYh7o/2Pzdc+NYJQVljek7LebqLLmZ9tRqlAJ5BKQ+epVbzIPN/3ODnoLqWJuIkujLC3RVyP9qGO+5eWmRtv6Cy3F1rb892NBK6BBhb8DPn7StaKXePMeUBhj8Ya2oser9xUW6iuRdqE/a/6yInWPp6MFf99zpLrR7R2htod7dLw8mYG2VhHkwkToPtL8esHFcVB8pYuln1ObcQOtZIxTJx6JpuOVuMnmo2ZjlaTGefFOh6ojFjrFV8MKHc9O1II6i2uipG51iCC3/s8dHtzeodaw+ZcVxh/xvrdadfyW5gTL0putBnh8pZyAPIrgCqTI3Pau47YGF5ur8z0lJmUXwQtXjzVqLb/6+KaPh/XHjCTYRMOZprsr/nPaluI7h2f7HCPQ+kZ7K0ifo0kIZF29wT0lKzWX5aZk/54H142LnI+201PxIT0n9XtGxf0UsykxOy69ifHDte6zy2aC9zKWt/qJPTjQ4/BrfmJXXR8o+yIOITqYhLfBGQPrvRthSGvvI/VWuQN/A29J2fRAB9fc54Ebg5/b6i/N2Dxfs+mMD5EEEgprKf89vXO/wDj1xJjIgDyIQCFEHeRCBQIg6yIMIBELUQR5EIBCiTlfx4O/ZLBqS79lsPeyVQWopCrmwFZshw+LIg/S2CC0lb69ZLJj298xVR/y+NDTEXbeyuhxW0dKYeHuv1YUXJaz/XE89FQfx00ObzSvmTJkydekBr4yGVsJre8sdTuR5Nj6577M6/5x2Zo72iTfINH/3O2l12CuTPPsGWxOoIBAIFukiHvx1G6fvj0Cr0VpzHVMbsSeiNA2mGI9TUzY6EvX7Pk/C+2MT1TT+XrXBZLyy5kq3dH/yvAC3f7Q0hO7W01h0/Tvr9wNQTcVBaoyxN128wcJq/VRdVb3doTVF90xVNTf7EVsbXu4dpWHiTHvn/f/epdGYZDddw+hEdEMtmxOo8Jz//vuvpaWF1NwsCKEZsvIfGX6XCkKY6FIe3Ox4ZZnG6J0BZS3ke+TPTlM3vZuXcHGa6m8Pqq66+vT4VFUD6/CG5lzXJapa6+8/tNBQN3H+2sy+B6mm4mibK6jW31xbxezez5/gQQ3Tax8+fby7ecRvD9JMvKFsctL7kU9QXEH9bw9Wv2NzAhUeAroh1tdX19QSqqoqKivLyitKy8v5FcrKy6trauqI9Q2NjSQSqQWpEIGbruRBBS11dc2Zdh8p01Q0vLIer701gJDYwYO/5rqYb59GaiU+s9BUX3jV+8A4VdVJa/duXzxaWZ0dD1JPxUEi5T4/vXbWWF0dVWVl1TUPS8j9wbZnktR/eZBm4o1hKrrDdTUVlCbsfPbmPMWDlQFsTqDCK0CCcXFx2jpa6hpqauoQVFXV+BxsDtkUFRVVEAhgwyakQgRuupIHVRZus5ispGnm9h2bJ1l7sm18XUcPqiw+7rR9guqUU7GN0I1bp6Zheic7wdV82niDv5csM9Zgpz9IMxVHZfCO0cpTDwd9zn6wRVdtk1812YPqJqeeBT2zN9X93R+knniDPC6uq/1372j1iUfvnqF4sOpfNidQ4RUwAvXx9ZGSljxz5vRl+8tsB1MzU1k5mQsX7DhJBIKystLcuXNSU1O/5+RA97Cuvh6GyWiAjMBDV/KgmoVP5l0zbfVJJ8Lf39s+VXOUJXkCkw4eJF9A9Nusoz7R6vajS6tGqEw+3rZIDXvj4obP1FNxXPZzNNNQMt53z+/q2rGqqpt8q/BdH1Qy3nr+1KaJqurzHZ+epXiQWMDmBCo8AfxCIjV7P3ok302usrKSk6Tu3r3bq3evhgZORT9p0sQpU6eEh79KSkzMy8sjVFU3NjUhDyLw0LU86FdX8/rQJCXdlRbzh+ua2MeSJzD5Hw9ChOgLJjrkGUHUx23xym7THnserPKhmYrDxvvu5lHKysM0Z23fukBjqev3H3/0YMnDjSOUFZUVVPWMTC+++pHw63eSVjYnUOEJ4BewzEMvL4HyoIGBga+vb2RkZGZmZll5eUNjIxoaI/DQRTzIEqTKnNSkjEIuTGlBfyoOUmVuRoepVziBSxOocB/wIFjG88EDgfLgmDGj77jfCXkRkpz8qbikuL6hoaUFeRDxZ0TRg9xDJKbioAt4sJ7sQU+B8qD+SH0XF5eAwIDExMTCokIi8iACH8iDCHYQTA/q6es5OTk9ffbs48ePhYWFxHrkQQQukAcR7IDTgy0tLUQisb6+nsnvFVz24LVfHvyJPIjADfIggh1wejAyMlJZRUlbR4tJnD96sKioyPqA9YaNG+Lj4phkCTw4Qm8E8iCCDZAHEeyA04Pn7c5LSkn8Jfb/YmNjGcVh7kESiTR7ziwZWen+A/r1698XnMgoHeRBBNsgDyLYAacHFy5aaGhoICcv6+LiwigOcw+mpKSIiYsdPHjAz9cXfOrm5sYoHeRBBNt0KQ9SHvj/r5nDB/WbW5opj+pzIycczT7Q/HvWAG6VDxfB40FQm4LisJ07d8DQ2NzCnFFSzD348MED0N/Dhw8/f/4MG7t27WKUDvIggm26iAfbHvivJFSVV1aWlpWzF8orKmrr6iCpxqamZraeyoKP1NTWQkolpaVFxcXQGn/8/FnAYvhBCXAsdfX1DY1N4ERBsyEeD2ZkZEhJS96/f3/qtCljx41llBRzDzo42IP+/P39v337Bhur16xilA7yIIJtuoIHoU3Cea+lpamqqqKiqgxBWQWCEutBWU1dNTAwEBRWVVNT39DAxgOq0IPT1tEeOGjAgIH9yWEAOfQf0I+lgH3qoM3B4uKSSgIBvNxEIgnUI2J4PAidODDX5cuXZ86cAUPjuro6utGYe9DJyamjB7ds2cwoS8iDCLbpCh6EseOTp0+gkVy6dPHKFUe2g52dnYysNPzNyEgv+PmDUFUFfTFIHH9OwA4gLOgEWVpu8/C4z0nQ0dVZvmJZWlpabm4O9FKhSTezkpPOBo8H9+7bC5UiKysDBSIm/ld8fDzdaMw9GBISAom4urrGxMTAxnm784yyhDyIYJuu4EHotfn6+UEjIdZz9DBbdXV1j549bGxsoqLepqd/LioqqiUSIXH8KYA0oRcJzf7BA09OcgJMmz5t3ry5ERGvP31Kyi/Ir6quEagu4R892NzcbGhoMHTYkPKyMqxj6O5+h25SzD1YWlrap29vo4lGGzduEJcQ+/DhA6MsIQ8i2KYreLCJ1Ozj68MtD1paWsLQOC4uNic3p6q6miX7QJcN1MktD06dNtXP3//t27dZX7KgSwidUyHyIIFAgMI0WWgCMdPT06WkJK2sttNNirkH4eNut9ykZaSgR7nf2ppJ9xx5EME2Qu9BysQnpEePH3HLgxs2bID+y5uIiKysrAoCARLHaR/yVFTNzdW1tdzy4MRJRuCI0NDQ1NSU4pLS+gYBmj3ljx4kkUg/f/4EG7ZSusmFhYXl5eV0k/rjfdSwL+gVQqeYeUUgDyLYpqt48BHXPLhq1SoYwb0MC8tIT4deGMserKnhlgcnGEy4ceNGYFBQUlJSURFl9hTh8SB+uPhcHfIggj26hgebvLnnQTMz01u3bv3777+f0z+Xse7BqmqueXD8hPHXr18PCHiWmJhQWFRERB5kCvIggm2QB9vBPGhq+tuDn/nvQWcn52fPkAdxgTyIYBtR8WBubq7+SD1tHa309HRGcXjjQQKBsGvXrhkzZ0D7Z5Ia8iCrIA8i2EZUPBgcHCQm/peYuJiHJ0ND8caDm7dslpaR0tHRlpCUCA8PZxQNeZBVkAcRbCMqHjx69KiikqKiksKevXsYxeGBB8vKynr17rlo8aLMzExJKQnL7ZaMUhMWD0pIiq9cabZ+/Tq2g9FEIyixNWtXc5IIhAED+iMPIthDJDwIcWbOnDF37hzjKZMhMLoHjQcehPYJ3dIjRw43NjZCT+rvyX8zSk2IPDh33pyFC03YDqNGj4SvhAUL5nOSCIQ+fXsjDyLYQyQ8CIIbOGjAwYMHtlluGzhwAKMHXXngwRcvXkA+bW1PwXb3Ht309EcwSk1YPIjGxYgugEh4MCUlBd49dOjQdqvtsAFjUrrReODByMjIjh6cYDCBUWrIg6yCPIhgG5Hw4O3bt+FdaRkpMBRseHl50Y3GAw9+//5dVk4GuqXFRUUystLrN6xnlBryIKsgDyLYRiQ8uMV8i4yMNLSN8PBwMfG/bGwO0o3GAw+2tLSA3QYPGWSx1QJy4uPjwyg15EFWQR5EsI1IeFBPX09TSwNaWnl5ef8B/WbOmkk3Gm/um4n/ED902BCQ4KbNm0gkEqNoyIOsgjyIYBuR8GBGRkZubi4W+Wv2V4BuNN54kByNRKquqmKeLPIgqyAPIthGJDyIE/RcHX5wejDt82dTsxXrN6yvra1lFOePHkxJSbn/G6gjRtGQBxFsgzzYDvIgfnB60MmZPKs+BChMRnH+6MEDBw9ACuISYhCys7MZRUMeRLAN8mA7yIP4wenBtWvX6OjqSEpJeHp4MIrzRw+amplqaWslUGASDXkQwTbIg+0gD+IHjwebm5u1tDXXr183ZOjgPXt2M0rqjx6cOGkiFAVUB5qHFdFJIA+2gzyIHzwezM3NlZOXu+5y3dDQYMpUY0ZJMfcgvD5mzGgZWWkJSXErq+3NjJeLQR5EsE2X8qDZSrPVa1azHVaYroARHFc8qKqmMn78OE5Cj57dhd2DwcHB2JKbS5ct7d2nF6ObhP64Pgl8P2VlZY2fME5cQozJtGnIgwi26VIeXLjIZMnSxWwHE5MF3PLgggXzbWwOchIUlRSF3YPHjx+HSpGTl4VSBYWlMfipBOd9Mw4ODpDay5cvGUVAHkSwTZfyIBoX84w/ehAizJo1E7qBL0JfHD9+DGrn0aNHdJNi7sH6+vpv374VFBRMnToFRsf5+fmMsoQ8iGAb5MF2kAfx80cP1tbWDhw0YNr0qRAzISEB+oM2h2zoJsXcg2/evAH9desuLyEpcf78eSZ1gTyIYBvkwXaQB/HzRw8SicRHjx/FxcVh235+vu/fv6ObFHMPVlVVQQnccb+TkpKCfi9GdBLIg+0gD+IHPVeH6EogD7aDPIgf5EFEVwJ5sB3kQfwgDyK6EiLhwZCQ5/Pmz5syxXjpsiWenp6M7sXljQe/fv16+TdfvnxhFA15kFWQBxFsIxIevHTpIrw7Z86csePGion/5evrSzcabzx47949yAzEkZaRCgwMZBQNeZBVkAcRbCNCHvT39//06RNs7Nu3l2403njQ1vZU3359kpOTc3JyGK0Y1So8HoSDtbW1hRJmO6wwXSErJ3P+/DlOEoGgrKzEFw++fft2ydIl1gesYZxhZWWVnZ3d2Ni4adPG0tJSPz9fJ6drpqYrLC0t379/v8Bk/rHjx5qamjo7SwhWESEP+vn5OTs7wwaj2fB540FzC/P+A/o9f/68vr6eSWrC4kHoX6uoKqupq7EdBgzsD4moqqlwkggEGVlp3nuQSCTqDteNiYnJyMiAfzW1NBMTE6FvO3jIoLy8PAcHex1dnYSEj2PGjJ45cya8payiFBsb26lZQrCBCHlQXEIM/sJXN6MhGG88uGbNaugPQssfN34sk1lFhcWDcvKy5eXlLRxw586dnr16glA4SQSYONGoMzxYU1PDpNsO2dbW1nr58iV2ktB6EL724PXdu3dBhxc2Fi1e5OnJ6W9oCK4jQh7cu2/v2rVrYOPcuXN0o/Hs9+KqqiqLrRaUlfMeMoojLB7s8tcHN27cMHzE8Pj4eEYRXr16paSs6OLi0krPg5bbLeH1PXt229mdh42lS5cgDwogIuRBf3//4uLiXr17auto043Gy/tmIH3I0pUrVxhFQB5klU7y4NevXyHlbt3kHRwdGF3ag0ExqLCkpAQ8mJCQUF9fP2jwQORBIUKEPOjl5RUSEiIpJTFz5gy60XjgwebmZuhZQNMyW2kG4/S3UW8ZpYY8yCqd93sx5O3w4cMystLzF8yjmugBxuOgv9LSUi1traKiopmzZvzzzz8RERHy3eSRB4UIEfJg3359pGWkBg4aEB0dTTcaDzyYk5MjJy8LEcTE/9q/fx+0IkapIQ+ySqfeNwMl/zLsJXT6FBSGBQYFtp0SVVVVpmams+fMvnnzJrwIp83IUSM3bd5karqioKDA09Pj/Hmy/i5fvuTufgc2rK33BwcHcyVLCC4iEh7MzMyAxnbr9q3Q0NAqxgtm8qY/mJSU9CzgWVZWFlq3E0MoPIgBXb/lK5bDkGLvvr01NTXYi/Bl1nZnPhQLbMNfePE/CthXHfZvxw2EQCESHsQJeq4OPzg9CGPD06dtL126xERzTDxYRSCA0SAR7F+QSGJS4sePH+hObc2b+6hh1zdv3ujeo9u48eM+JX/ibuIIfoE82A7yIH5wehAGg1AvYuJ/MVlvk64HoVfl6uqqpKQIH9+xwwrbo7W1tYSkuLiE2NZtW2kvKfDyeZJPnz6NGj2qR8/ut2/fYnJxAyEsIA+2gzyIH5wetLAwV1JWAnMxepaxlYEHm5qaJhhMmDptapsHoTqgYFevWbVmzWp4MS0tjSodHj9XV1dXt2fvHhgjr1ixvKioqJP2guANyIPtIA/iB48HIc7IkfqmpisGDBxw5MhhRkkxGheXlpbGxcVBXxLzoIuLC1RxUFCQn58fbLi63qSKz/vni+EAnz59OmTIYFU1lfDw8M7bEaKzQR5sB3kQP3g8+PPnTxg5OjjYjx4zes7c2YySYnJ9MD4+vs2DNodsoIrBjBEREbBx/Pgxqsj8mmchPz9/ztw50jJSx44d5fzXHgRf6FIePH3G9rzdebbDqVMnpWWkueLBefPm7rfez0lQUFQQdg++evUKW2HObKUZdAkZXUfD6cHde3ZDavDKmzdvYOPw4UNUkfk43wyJRLp06ZJ8N3njKZOzsjJ5sEcEd+lSHlTXUNPQVGc7qKmrQqvjigfV1NUMDCdwEqBnKuwevHDhAlTKoMEDKassiX/79o1uNJwetLtgB6m9ffs2NDQUNv755ypVZP7OuwUFEhsbq6Wl2a9/34cPGT4uiRBMupQH64h1/3FAVVVV9x7dueJBT08PTnICTJ02Vag9CBFMTBbIycvCuHjdurVQO3AgdJPC6cHw8HBIxN7+8tmzZ2GDdtYWQZh/EE4hc/MtIP0NGzeUl5fzctcITuhSHkTXB3nGHz1IJBKVlZWMjAwhZkxMDOjs5MkTdJPC6cG6ujoDgwmycjLg1snGk2knFRcED7ZS7vjx8vLq26+Pjq4OmmJLWEAebAd5ED9/9GBNTc2Jkyf8/f1gm0AgnD592sfnMd2kmHiwoKDg+InjQUG/Zu0uLCw8ZXvq7NkzJSUltJEFxIOtlML5+vWrsfFkUPaly5caGxt5nwcESyAPtoM8iJ8/ehA/QvRcHUuA/k6ePCkjKz1r9qzc3Fx+ZQOBB+TBdpAH8YM8iAcopfDwcBVV5SFDBwcEBOA8kRC8B3mwHeRB/CAP4qe8vNzMzFRCUmLnrp1MZiBH8BER8iCoxN7+8u7du8LCwuhG6GwPEggESDYmJgb7t6WlBbZBc/A6bWTkQVYBD+rp6wmgB1spNxi63XLr1avnmLGjE5MS+Z0dBDWi4sGMzAwlJUUx8b9kZKWvXqW+9QyjUz3o6empoDgMMmlsPBl7xd7eXlJKgrJQyTjabgLyIKtgHnR2dsY8WChIHsRITU0dO25s9x7dXG64kBgsoo3gCyLhwebm5vkL5oFxoMnBNzOjheI61YPm5uampiukZaQwD0IfEBr/9BnTLl++DDm/f/8+VXxh8SB8r7x8+TKaA44dO9ate7fIyEhOEgH09fVGjtS/4eISGBiYmAAlVkguMUHyYCvldiLrA9ZS0lJLly0FU3d8C05LNHUNvxAJDxYXF8vJy44eM5q50TrVg7W1taWlpdDgMQ9idwWDBL98+QIb2OztHRF8DzY0Nj4LCIBvF8i/gAQjI0N3d/cXL14kJycXlxTXC54HWylFFxgUOHTYECVlxbZLNPDi3n17X4S+4G/eRBaR8GB8fDy8u379OuZJdfb1wbKysjYPenh4QJbc3e/Ai6CShQtNqCILvgeh2MsrKuM/xEMOb9+5DcN8W1vb48ePH+UHsF/Y+40bN3x9faFrmZmZWVZeDqYWnBKj4ufPnyYLF8D44PDhw9BJfPr0qaSUxIyZM1CXkC+IhAdh0ATvbtiwnnlSvPTgndU8tboAACAASURBVDu3O3pwgckCqsiC78EmEqmmthbac2pq6tu3kUFBQT6+Pl7e3g/5gZe3l4+PT0Bg4OvXrz99SsrLz6uqrsZfd3yhuZnk6OjYrbv8BIMJQ4YOhvMBzpwPHz/wO1+iiEh4MDcvV1xCzMDQgI/j4tb/9SCM3SDD16875+XlwcY2y21UkQXfg80tLTDwrKiszMvPT09P//jxY/T79++iot7yg6ioKNj7hw/xaWmpubk5ZeUVxPp6EmWpEH4XFTMge/AlLScv2za0X79hvYDnuUsiEh5sbGwcP2EcRPD09CgvL4dhCN1ovPRgYWEhnP1mZmbYAFnofidp/X28kCtCVXVxSWnBjwIQ0Pec7/wh5zvsvaCgoKi4uJJAqKuvh+6qQBUXXaAM7ezsOl7ilO8mB0fD73yJHCLhQeDfly+7d+8GI9C+/fq4ubnSjcNLDwJWVtvJ9/HISI/QG057C6Hge7D19/JsDY1NxPqG2joiDJOra2r4Fmpra+vqwIANjY0kUrOglRVd3r9/LycvR/Vrz9GjR/idL5FDVDwI0T5/Tjt16tR+6/38Wr8Y+qE3bt7Aph5opawODv1TR0dHuqtbCIUHWylHjY2RQYgkfgcyLb+WzOR3wfwZyOTTZ09tbGzWrls7bdpUHV3tXr17wihh0OBBVVVV/M6daCEqHsQDeq4OwV9A48XFxWlpaXQfMUJ0HsiD7SAPIhCiCfJgO8iDtNTW1vJ4jwgE70EebAd5sJVyFPkFBSEhz48dPzZr1syFixbi/BTQwu/QRmeXklAjIJUlUPWFPNiOiHvw9p07mzZt1NLW7Hg727lz55h8hNycWsg/GTeRSA2NTQ2NjfUQGvgRGhsbKAFOBhLlxxJBaF2CBvaLFlQWlBJWXIJQX03kX/f5XF9dyoOvwl9FcQC4T05ejisetLAwd+cMbR0tHnvwsY+PtIxUxxs4xCXEU1JSmBxvJYHgfvfuTVdXlxs3nK9fd3J2uubkBH95H7D9vnv3DrJUU1cHUhb8m6h5DJw8/7586ebmduPmzesuLk7OzlBofKwvCAGBgRWVlTW1tfXkCuPnwz9dyoNcCVzxoLy8XO8+vTgJEpLiPPYg5P/GzRviEmJtRTFixHAma2tAZvyfPIFoPXv15ORIse5nr94cFRdWYosWLfz+/XtRcRHUAvQ1mtGzur/BTk5FJUW+z4XRMSgoDsvOzv5RWAjfXnB683Eusi7lwW/fsn/++MF2yMrK6ta9G1c8eP/+vSbOmDJ1Cu+vDyYmJfbr37ftND18+DDzg330+DFYrKSkhJMjvX37Npi0pqaGwxIzMjKcOXNGXGxsRkZGYWER9Ar528UQKFpaWuCLYZjCMKhTTtoIhMc+j+HcSExM5DAdc3PzQYMGRkdHp6WlFhQUEMjPgzfx646ILuVBdH2QEyIjIwcOGmBgMMFyu6WY+F/QMXzP4Ibz1t/zLHh5ewvUPKwTJ00MCg6OiYmBXgYMuGCwhTyIAV3jOmL9MIWhdnZ2HCb1KvwVtLWfP39ymM7evXv7D+gHp3fU27fw1VVSWkokz8CIPMgWyIOcAzl//vx59+7dZs2eWV5eDmPhjZs2KikrMRkUk+cfbGp68PChQHlw3Phxng8ehIWFpaWlQbsSzPkH+QKcmTW1tYLmwT59+0Dth4SEJCUl/vj5s5ZIbG7mz6UM5MF2RNODkG13d3cZWem169a2zUBRX18fEBDA/FMCOC//qFEjXV1dg4ODPyUl/Sox5EEKTSTymSloHuzdp5ezs7P/kyfxcXF5+Xlg6mY+XSJEHmxHND1ob28PGd6xY0dTUxP+TwmmB/X09a5fvw4llpCQQF6fBHnwNxQPVg8dJnAevHLlio+PT0xMdG5eLvIg+yAPsg0Mew8dOgS5tT1tSyKRWPqswHpQMNer4ztNJBKB7MEhAuVBqHcHB4dHjx5FR7/Pyc2trkEeZBecHmxobIyIeP3q1SsmD4rxxoN1dXVfflNTU8MoWmd7EEa+m7dslpaRgg4UGz8m4PEglPalS5fOnTt7//790tJSRkn90YMVFRVtJcak0yqw6xcLAjg9mJeXFxYWFh8fzyQOEw/CWQGndNvVFais6t/QftEiD3ITnB5MTEzE7oyLjIxkFIc3HvSh3K6MhcDAQEbROtWDcLIuW74UFObt7cXeL6p4PGiy0AQKXEVVRUJSXF1DnVG0P3rw5MmTbSWWnZ3NKBryIBNwenD37l3YbX1Mzgq6HoT4KSkpixcv6j+gn4WFOfbi7Tu3+/fvh4Xw8HCqdJAHuQlOD4LaZOVkodE6OjowisMbD9rb20M2zp0/d/XqFSatuvM8WFxSMtl4cu8+vaG/xnYi+D1YUlx85uwZ2AgIeEY32h89uGHD+sFDBkNxQWAyIRXyIBPweBAcZGAwAUQmJSUJHUNG0eh6ED6rrqE2TGEovLVypRn24qFDh+Cry2qHFQRoTVTpIA9yE5weNDffMnLUSF1dndWrVzGKwxsP7tq1E04XJiNijE7yYH5+vv5IfdBKbFwsJ+mw5EFb21Ni4n/FxcXRjfZHD06ZOmXatKl/vIKJPMgEPB6E7xiozVWrV0FlBQUFMYrGaFwcGxsLJ2pHD0Jb09TSZJQO8iA3weNBaEIgwTVrVkO/XU9/BKNrTLzx4LJlS+E86z+g/+nTtkwWaewMD6ampsL4VFNLIyMjg5N0Wlnx4MSJRrJyMjaHbBgdLHMPQmXpDteBkbWikoKHhweTukAeZAIeD76Negv19fDhQ6gvODkZRWNyfTAjI72jB/+ePElaWsrQyMDX14e24pAHuQkeD5aUlMjJy164YHf4yGEZWRlG7ZY3HkxKSvL39x89ZpS4hNibNxGMonHdg9HR0UOGDh49ZnRBQQHbibSB34NmZqYDBvZXVFLM+vKFbjTmHoSGERMbAwaEzMO+fvz4wShLyINMwONBe/vLYMDc3JwhQ4csXrKYUTT8HvT19T1z9sygQQNhdIzGxZ0LHg++ekWuOSMjwzFjRsNGVFQU3Wi8vG8mICAAcgInAaMI3PXgvy9f9u7TC0aX8JXAXgpUsDQu9vf3g429+/bSjYbzvplz589BIlAvjCIgDzIBjweXLV8KHoS/ffr0VlFVZvQ0EX4PYri6ucKLN2/eoIqMPMhN8Hjw3Lmz8O7ceXOnz5gGG9euXaMbjTcehNMLYjo4OkJO4AuTUTRueRD29eDBAzi/l69Y/seLkiwli9+Djx+Tn8zfvWc33WjMPQijaRgaQ/PYvGWTmPhf6enpjLKEPMiEP3oQynnosKEDBw1YtmypuoYanDCMlg/F6cG2OVavXL0CL8I5QBUZeZCb4PGgicmCvv36QHPNzc2FLvrmzZvoRuOBB8vKykaNHjlxopGMrDRswB4ZpcYVD0KWnJydsPkQOb9RmSplnB6cO29On769e/TsnpSURDcacw/Cp4aPGD5u/FiQIKicSTtBHmTCHz2YlZUlKSVhabkNth0c7KHiQkJC6MbE6cG8vLyFixauXbcWql5NTZX2h37kQW6Cx4NmZqZbt22FbzwikWhqtmL79u10o/HAgxUVFUePHV29ZjWM8soY31rcyg0Pkkikk6dOQWaOHD3C6uMifwSPB69fv2620nTtujW2tqeY/DLD3IPZ2dl79+6B5uRyw6Wuro5JlpAHmfBHD0ZFRU2bPhVONtiOjomGbe9H3nRjMvFgXl4ufPDMmdOw/fXr10WLF40fPw6+g+neH4Y8yE3Qc3V0Aa1st9oOOXG84shhTugimM/VIQ8yAj1XxxzkwXa6jAdra2tXr14FQ+/79+8zuTWHE5AH24iIiJg9Z9auXTuhDZtbmEM/qLGxcc3a1SUlJY8fP3J0dFy0aOHmLZvfvn07c9bMgzYHWZrPglsgDzIHebCdruHBsvLyGTOnwxn2PCSk82YhRR7EIBKJ2jpaKSnJOTk5UCaaWpqJiYlwLIOHDMrLy3NwsNfV1UlNTR03ftys2bPSPqepqKq8f/++U7NEF+RB5iAPttMFPAhn5/gJ44YMGQy9Dw4zwBzkQQzwoI6u9vPnz7F/aT1osdUCXt+1e9e58+SV/6Bv+MCT03ODDZAHmYM82I5QexD2DiMyHR1tRSXF5ORkDvf+R5AH24iMjFRSVrx27Rrd/qDldkuIs2fPbju787CxdOkST+RBCsiD3KSjB7O/Zf/ggMzMTG6t0+To6JDNGYZGhix58MPHj4OHDNbT12PyhDwXafOgrJwMtHxOjvTSpYvde3RPT0/nsMTGjh3Dr99J4MRTVFQoKSnR0taCiqivrx80eKBgevDw4cOctBHg0WNyW0tISOAwHXNzc+RBrtHRg3LyspwEWTnyApJc8SBXVjXE78Hw8PD+A/pNnvx3UVERV0uX2cFiHuTiKo6cB957sKWlpaysrLy8XEtbEwp/1qyZV65eCQ9/JScvJ5gelJSS4LCZSMtIQ1HD9x+H6UhKSiAPco2OHgwKDnrJAWAcqB6uePDs2TMfEz5yEsaNH4fHg7BTPz+/Hj26z18wn8ld2VynY3/wzZs3nBzpyVMnoRseExPDYYmNHKnPew9WVVUtX758+vRp7u7uUCavX4ePGTPa3MJ8zdo10OV5+PDBhYsXIBqMD+7duwsbNjYHGd2f3Km0eXDTpk2ctBHg4qWL0Na8vb05TGfJkiXIg1xDlK8PQmfE7ZabtIzUxk0bmd9jzHXQ9UHhAl0fZA7yYDvC5UGQIJzTEpLi1tb7G3l+SxryoHCBPMgc5MF2hMiDTU1NcBpJSklcvHiRizcJYg/G44yJPChEIA8yB3mwHWHxIJFIXL9hvbSM9K3bt7j7uMiPHz8sLbfh+cUZeVC4QB5kDvJgO0LhQQKBMG/evG7d5f2f+HP9cREwoKycDJyd586dq61lNkkX8qBwgTzIHJHwYG1tbVZWVlpa2vfv35nMvMJ7D2KT69F9i64H8wsK/p48acDA/hERDCey5gTMg9g9KOoaaj4+Poyyh8eD0LuMjYl5+/YtFD6TYmfJg1DCjJISXg8WFxd30mPgbeDxYEFBAZzz6emfy8rKmCSFPCiI4PHg1atXJKUkIIKMrLTxlMmM5mTuVA+CLA4fPqSuoW5mZoq9kpycbGBooKSseNn+Mu0uaD2Yk5enp68HR2FsPHnnrp2dETZu3CAhKd52O564hNi06VMTExPpHuwfPbho8SIsHSiQpcuWNDGY35iRBzMzM1evXq2iqnzl6q8pc0JCQnSH62hpa/r6+tKWmPB6cM+ePcuWL8vKyuy8XeDx4MBBA6CyxMT/6tuvz4ULFxhFY7Rup7X1fv2RehMnTXz8+DFWO9DtMDFZMHzE8KtXr9KKHnmQm+Dx4CXKHU9QGTDcgw34Szdap3pwwYL53Xt0g5MMLNZK6QmOHKU/aPDAKVONwdHv3r+jik/rwfSMjMFDBkH+Bw8ZDDbvjDDBYALksOOdyUOGDgZP0ZYA/nlYU5KTN2zcABthYWF0o9H1YB2R2K9/v569esAHT5460UpZZKb/gH7gQT39Ed26d6P9MhNeD+7YsQO7M/nwkUPM+2Jsg8eDcH7Ct3JCQgJ83UK1MrpMzKg/uHvP7p07d/Tp2xvOf/gsdNvhVIcaNDQygPjwKar4yIPcBL8H/f39U1JSYOPo0SN0o3WqByPeRMDeoQFjHkz69Al6XocO2cTHx0OWjh07ShWf7rj4y5evMC6Gc+vOnTudMZLqOC6Wk5c9cMCaUd+ZpXn5nZ2d/2K8tAhdD8LRBQUHQZW1edDb2xu2Hzx44O7uDhvQeKjSEXYPYgFMdPv2ba7PzYXTgxqa6rCxectmaRmpr1+/0o3GfFxsabkN3o2NjYXmAw3BcrslnPYwsKCd/Bh5kJvg9+DWrVunTZsKXaqsrCy60Tr7+iB81bd5EFu6yM3Nrbi4GDZMfw+W22D0OwmRSIRTCrqQ2yy31dbW4skYfjAPwlm7cKFJ2ufPTA4cvwf3W+8fOmzo7DmzGV0BZHJ9EGqhzYOnbE/BdnR0dHh4OGycPXuGKnIneRC+q7S0NDs19Ord838fEPzLyMgwneO1VTuC04MDBvaHCD179dy4aSMjJTHyYHl5ubOzEwyuJxtPbmxsxFYiu3r1SlFRERwgND2q+MiD3AS/B/v26wPfcoaGBtn0Zglv5a0H3SiLeLm734EXYSg6d95cqshM7puBvpKnpyecQxMMxmdy9aISeNDQyPDFixd/7Gzi96CyihIUyMJFCxlFw+nBnbt2wjZ0n9+8eQMbNjYHqSJ3kgejoqLOgnTPnum8MGHChI4eHKYw1O3WLe52CXF6EMYooEKor5OnTjL6PYqRB2FA3X9APziZ9+7bC5+9dcsNol2/7lxaWgpNb8zY0VTxkQe5CX4Penl5BQUHQ08K2iTdaLz0oI+PD2Tp9u1b0B+EU2f1mtVUkf/4PEliYqKOrvaAgQOCgoLwZA8P0Pbq6+vxxMTvwcKfPx0cHWDjzBnqHhwGTg+eOHEcG3Bh/cELF6jbcxcYF8vJy1ofsC5lunANe+D0oJq6KtTmsuXLYEwQFEz/vGLkQVAYnOEbKdeCg4ODsUUKwYMlJSV9+vaeOnUKVXzkQW7C0vVBqBLoosNIhG40Xnrw06dP4hLiR48djYuLo/x0c5YqMp7ni2EksnKlGXRyjx0/htNf3IKl64NhYWGwYWFhTjcaTg96P/KmXBb0vkO5PgjDLqrIQu1B6IjB13NGZmYnTSHO0vVBe/vLUMJXGKxsw/z64L379+Ddy/aXk5KSQKYHDh7IzMyEzoeVFbo+2Jng9yCU+7r162BjD4OFdHnpQahvPX29QYMHGk00gl5AaloqVWSc87BCOg4O9rJyMnPnzeHZpFutrHjQ9rTtqNEjyf0LBv1WnB6Eo4NhF3SBIQwaNJB2LWbh9aCLi0tISEin3kKI04NwQrq6uiqrKFGmlUygG42uB2FYs3///kuXL6lrqIP1EhIT4ItZT3/E4CGDFi4yERMXexUeTpUO8iA3weNBZ2cnyrxpUurqavut91czWM68sz1YUVExZuyYdevWYv8mp6QYTTSELMFXKJ77BxnNP0iZ7um1guIwVTWVqHdRnbcmCdVO/+jB7VbboV0pKCrAsTz0esionTPx4Lt378B6Ts7XsH9DXoSM0Bs+ctRIGBp3pfsHeQAeDyoqKUK3tGevHn9P/hu624xOJLoe/Pbt2/ARumBPfX29xz6/7h+Mj4/X1dWBEdjp06fR/YOdi6g9V8co/o+fP2fMnAEnopOzE9dXK6YFPVcnXKDn6piDPNiOUHuwlTL/wqFDNjAqWb9hPYFA4DADzEEeFC6QB5mDPNiOsHuwlXJLja+fb79+ffX09SD/HOaBCciDwgXyIHOQB9vpAh7ESE9PHztuTJ++vb0feaN13DlMtmuAPMgc5MF2uowHWynrZqxfv15SSnLfvn2NDCY44ATkQeECeZA5yIPtcNGDbm6uBM6YbDyZEw+2UsbIrq6u3brLG08xzsnJYbdUGB4s5kE5ednc3FxOjvS6y3Uo9pKSEg5LzMBgAvIgI5AHmdOlPKinP0J/pD7bYYTecHEJMa54sGevHgMHDeAkQCIcehAjOjpaVU1lmMKwsLCXrJcus4NtW7dzwMD+nBxpj57dxcT/GjCQo+LCSgx5kBFtHhw8eBAnbQSCqpoqVLrucB0O0+nfvx/yINfo6MFDhw8dP36M7XDQ5qCUtBRXPGhpuc3D04OToKOrwxUPtlLuQF640ERGVvrSpYvcemq1zYPSMlI3b97k5EgtLMzl5OXc3e9wWGIamurIg4xo8+C0aVM5aSMQ1qxdQ34YYe8eDtOZMGE88iDXEMxxMd+vD1JBamqytbUFZy1dtrSsjAuPr6Lrg8IFGhczB3mwnS7sQSx7QcFBMH7U0dVOoDfFNKupIQ8KEciDzEEebKdrexAjNzfXaKJh9x7d3N3dOTnnkAeFC+RB5iAPtiMKHgRqamqwCU6sdljRzlaAE+RB4QJ5kDnIg+2IiAdbKbPUeHh6QK/QwNDgK4NZaZmDPChcIA8yR7Q8SG699fWMvCY6HsRITEwcPmL4gIH9A4MCWX3sBI8H6+rqoLUUFBRUVVUxSQp5kAew5MEmCozeRR4URPB70MfXZ/yEcUpKiowmmOxUD0IFe3p6LF6y6NChQ9grQUFBC0wWYIF2TRweeLCVMiWiqZkpZPjEieMszVKDx4Pr1q+DLqecvOzgIYMOHznM6rxbBALh3PlzUDgPHj7AXnF2dmorMdrcIg8yAacHS0tLray2q6mramlrsrpeXSvlrHB3d9+/f9+PHz/g3+iYaNjGQgbNcivIg9wEpwe9H3lLSkkMGzZ0zdo1z58/pxunUz24evUqbA1lbB5W4OjRo/CKuoaahqZGWloaVXzeeBAAoVy2vwy2mjdvbmFhYcfDYdQSWlmZh/Xx48ezZs8SE/8rOjqabjS6HiQSiaqqKliJYfOwAgsXmsjJy0FxQaDtsCAPMgGPB2GoNHGiEdTU1GlTN2/ZxKgXz8SD8HUO5wO8++nTJ/gXWya3Z68eEGhXbUUe5CZ4PAhtbMSI4bJysl8YLEWI0akefPjwQXBwsHw3+TYPrlu3dvgIXUYVzzMPYmAzuaqoqkRFRWGvwH4NDCcwejaZpXn5b968CRuBgYF0o9H1INj5ypUr2AcxD8IeR40aSbuwXxvIg0zA48FHj8mNaM2a1cxlxMSDmzdv6j+gX5sHLbZaDBo8qIpAgEDbf0ce5CZ4PJiTkyMuITZnzmzmSfFyXn5gytQpcJacPHUSG0RQwWMPtlIWq4OOAHjNxcXly9cv2NpjkZGRdCPj9yAU5qjRo3R0tRn1L3DOy19bWwum1h2u6+joSDcp5EEm4PHg1q1byQuuv6JecJ0KRh5M+5wmLy+3datFmwfnzp0zdOgQD08PuvWFPMhN8Hjw3bt38C58WTFPisce3L9//+TJf0tISqipqxFopk3lvQdbKR3ngzYHYTTau09vbAU12oX0MPB7sHuPbuDTnTt3crh+MbQlqMHRo0fBKzNmTKe92og8yAQ8HpwzdzaUbUZGOvOk6HoQqmP58mULTBZgXXjMg9B5V1JWgtqHb0FoXFTpIA9yEzweTEj4CO+uXGnGPCkee7CVcvbs3bsH8kZ7yZIvHmyl/J4zY+aMtrV0ZWSli4uLaaPh92BKcjKc8bDh4nKdbjScHsSAcfrsOeTmSnvtEnmQCXg8uGTpEihYKDrmSdH1YPT799ivbdsst8G7//zzT11dXSvlm9WS8grIjiod5EFugseDFAHJKyopMr85g/cebCWvVXad7rUzfnnQzc0NvsA7Lit+4eIF2mgsXR+EwTWT/jhLHoT9Wm63hBe/f/9OFRl5kAl4PHj8+DEoWHsHe+YnPF0Purq6wlcmBOynrR49u+fm5mJvYZcd3dxcqdJBHuQmeDwI3a7Vq1dBhGXLlz1+/CgzM5NuNF56sLy8HL4z3d3dVdVUBw4aSLvkJl88mJCQIN9NvqMEIWhra9Eujozfgz6PH89fMA82wHd0o+H0YGZmxo0bLv9cuwaRR44aSdtgkAeZgMeDaZ8/g8h69urh6Ojg7+/PqNNA14PQdnIpnDtP/o04NDQUzoqQFyEguL//ngQtIiUlhSod5EFugvO+mYKCgomTJmIN297enm4cXnowKSmpe4/ukBlNTQ3aWwpa+eRBKIG0tFTY45Urjjt2WM2ZO0dLW1NGRvp5CPWwHb8HIQwaPBD6GoxuzcXpwcePH0vLSMG/UI+0jaoVeZApeDwIdQpnPnTlsA4dozulmd9H3XZ98MOHD9jAQk5eFr7yaRsR8iA3wX8fNfQK09PT4+LiaC/ZYnS2ByFCCwVsG6q8qqrqPwq0kfk1LqbKMPmgSCTsWg/VW3/0IBwpqB+OETaYlCETD2Ilhn2WXNGNjbU1NYySQh5kAs77qKFsoRXExMRkZKQzuu+duQcrKivSM9Kxp7Z+/PgRHx+PneS0MZEHuQl6vpgvoOeLhQv0fDFzkAfbQR7ED/KgcIE8yBzkwXaQB/GDPChcIA8yB3mwHeRB/AimB/X09do8WIg82AHB92Au8iAnIA/yBYH14PXr16HEEhISkAc70kRqFkAP9u7T68qVK499fGJionPzkAc5oKMHzVaarl69iu2wwnS5pJQEVzwIA7TZs2dxEvr07S0UHhSXEANlc3Kkw0foSkiKz5w5g8MSA5mOGjXS1dU1ODj4U1LSrxJDHqQAHoQzc5jC0JEj9TlpIxCguqGtLVmymMN0tLQ1wYPOzs5PnjyJj4vLy8+vqUUeZJeOHly0eOHSpUvYDiYLTbjlwSlTjLeYb+EkDB4ySMA92NDYlPb585q1a+YvmA9tY+JEo/Hjx48dO2bMmNGjeRtgj2PGjhk3fpylpaWnp2dYWFhaWlpJaWk98uBv4MwEy2y32j5t+lSoKagm8oLdI4brDtfhV4C9Q4uD0UBISEhSUtKPnz9riUTkQTZB42K+AAfbRCJVVVfDcObjhw+hoaHe3t537ty5efPmDcDFhccB9nv79u2HXg+hMxgbG5v9LbuikgCmxll3XZ7mlpY6Yn1RcfHntLQ3b948efr0/v37bm5ufKksrL6glcGXVkBAwLuoqMzMTPjeItbX8+t7C3mwHeRB/GAHW0ckFpeWfvnyBVQYEREBNgQNBfED2O+LFy9ev34dFxebkZEBxQXdHzA18iBGS0tLQ2NjJaEqNy8vJTn5/bt3YWEvn4eE8LG+oBv46tWr6OjotLTUgh8FhOpqaMj8qi/kwXaQB1kCMtNIIoFu4Js8Nzc3KysLRqPQxvgV0lJTMzMzcnJyoNcDHVXoDLK66EoXBjs5ocNVUVn548eP7Oyv6emfU1NT+FhfqampGRnp3759KywsBEHXNzTAoBh5kE2QB/kIjLag8KFXCF/m5RUVpWVl4ET+hTLIA6GqqpZIBAk23CfqmAAAFmlJREFUM32YTwRpIV/KaAbdVNfWVhAIZeXlfK0scoA8VBIINXV10Fcl8U+CrciDHUEeZIMWylHDCBTUA2czv0MT1Bfkh/kTzSIL5an2FighaDL8rqn2+oL88L2+kAfbQR7khP8EBn6XhBDA7yr6H/hdGGRExYMlJSUrV61ctnxp2/SQtHS2BzMzMx0dHby8vLB/Gxoa7t69e/bsWdpFO1uF0IMIhPAiKh4MCwvD5sLz8/NjFKdTPXj27BlZOZmO63bu2LlDXEJMWkZKQXGYgMzDikCIJqLiwXPnzg4cNGDQ4IGHjxxmFKdTPXj02NGTJ0/IysliHgSvycnLmpqZ+vj6Qs6dnZyo4iMPihT19fVwvnl4emRnZ/M7L6KIqHjQZKHJtGlTjYwMZ82aychrnepBbFLStvmoQ0NDKcvZXM3JyYGNLeZbqOILkQfhwJtbWuDYBSH8+olEIAuKCgKBAMOUs+fOwskJYwJJKYkePbvTXRUL0dmIhAfr6uoUlRR27dq1adMmBYVhtKttYPByXv67d90hw+7ud+BFMfG/5s2fRxVZKDwIh0ysr6+uqa0kVFVUVpaVl5fyL8Deq2tq6oj15JswSPy8CQMPcIJh10k6hgUL5gt4trsqIuHBL1++gGvsLtgdOmQDG4x+KuGlB+/du9fRg4sXL6KKLPgehOONjYvT1tZSU1dVVYOgoqLK53Do0KGi4uIKAgFsSL4bQ5CKiwoovQsXL1J50M3Njd/5ElFEwoMPHz6Ad6VlpMBQsPH0yRO60XjpwfDwcMjJlStXvn79Chu79+ymiiz4HoQRqI+vDxzs2bNnHBzs2Q5mK82gZ3Tx4kVOEoGgrKI0d+6c1NTUnJwc6B7W1dfz99bcPwIj+HXr17VJUEJSHA2K+YVIeHDX7p1wkvn6+kL/i7z+2cmTdKPx0oOVlZW9evecMWM69FLJan76lCqygHuQfLCkZih2gZp/cMrUKa/Dw5OSkvLy8vj7vCoeQkNfwDkwZOgQzINTphoLcm67NiLhwQkG41VUlYlEYklJCZx5JgsX0I3G43XcL12+hDWAWbNn0V6yFHwPQrE/9PISKA8aGBjAt11kZGRmZmZZeXlDY6PglFhHoPS8vb27dZdfumwJ9AGXLF0Cp4GjoyO/8yW6iIQHAwICXke8/o+yVOaLFyH/vvyXbrTO9mBTUxM00YSEBOxfGBYlJCbCjugqQPA92ECeh/WBQHlwzJjRd+7cCXkRkpz8qbikWDDnH4R6v3btmpS0lIWFeWNjI7xSXVMzd97crKwsfmdNdBEJD+IEPVeHn/8Ecl5+/ZH6Li4uAYEBiYmJhUWFAjgfNYlEsrW1lZSSOHr0CGy3vV5XV8evKUgRrciDHUEexI9gepC8TpOT4K7TBOLbuXOHhKQ4DIHRnGACBfJgO8iD+GHJg9DTwQaAdOmk9eoEbd3OmpoaUzNTOXm5+x4e6PcQQQN5sB3kQfzg9CD0gOwu2I3QG66qpvL27Vu6cRh5EOz5/HnwgYMHnvy+zwm6eEePHT10yIbuHaCCvH5xeXn5nLlzevbqERgYiCQogCAPtoM8iB88HoQ4+/fvg3rR0x+xctVKutPqtDLwYFNTk8lCE3EJMfj4jh1WrZQncA0MDWRkpeXkZXV0dWi9KbAeBH2PGz920OCBb6PofxMg+E6X8qDtadvz58+xHU6ePCktI80VD86dNxcUwElQUBwm7B789u0bDAPBTfAFwyQpuh5saWmBQrCzs2vz4KtX5GVz7R3sL10iP4YRFhZGlY5gejArK0tHV1tVTTXpUxJ/c4JgQpfyoLqGuoamBttBTV1NTPwvrnhQXUPN0NCAkwA9U2H3oLe3N1TK2bNnmCfFaFwMu4iPj4cawTyI6S8iIiIkJITyKA713XYC6MGkpCT4PtPS1srJyeFjNhB/pEt5EI2LeQYeD16kPD/r7u7OPCkmv5N09ODefXshNXjlzZs3sGFjc5AqsqB58PXr13369v578qTS0lJ+5QGBE+TBdpAH8YPHg//88w95akVnZ+ZJ4fTggYMHOnrw5MkTVJEFx4NQOP7+/j179Zi/YD6HNxUheAPyYDvIg/jB48GwsJdQKaZmpswLEKcHXVyuQ2qhoaGgGNiAT1FFFhAPtrS0wPkjIyu9dt1aIpGjExLBM5AH20EexA8eD9bU1GhqaUpKSRw6ZOPr68MoGk4PpqWlQcGuXr3K1HQFpEl764wgeLC5udnugh1kz9p6f1NTEy93jeAE5MF2kAfxg/P+wXfv3g1TGIpNJxEdHU03Dk4PQj/L+oA1pAOvHD9xgrZS+O5B8m/c1vtBgmfPnkUPyQkXyIPtIA/iB//zJPX19aAzEBOj/hETD8K4ErqBPwt/tu00PT09MzOTbo3w14N1dXXrN6yXlZNxu+WG7pQWOkTCgykpKRcu2J04eeLq1SvpGemMkupsDxIIhNDQ0JiYX90iGNk9/w28RRW5y3jwj3DxuTp+eRCqb9GihXLysv7+/jzYHYLriIQHsVvPFJUUevbqAe02JiaGbrRO9aCHh8cwhWEd1+3EbhLGQttkXG0gD7IKvzxYUlIy2Xhy3359wl69Qj1BIUWEPAjf1W8iI2HjwIEDdKN1qgfNLcwhZWkZqTYPbt9uOUxhKPQQw16F0T5xgTzIKnzxYHZ2tv5IPSVlRdhjp+4I0amIlgdfviTfyXHt2j90o3WqB2tra0tLSzvOR21ismD4iOH5BQV000ceZBXeezA9PV1FVVlbRys9I6Pz9oLgASLkweEjdHv27DF7zmxQEt1oPJ6X38DQQFJKAiLv2buHdjY65EFW4aUH4fDfvX83YGD/8RPG5efnd8YuELxEhDw4Z85sPf0R0G79/f3oRuOxB3/+/AnN1cBgAtjww4cPVJGFxYMSkuKmZqZr161lOxgaGUpKSa5avYqTRCD0H9CPZx4MCgoiL7M1cwZ6XKRrIEIehHHx9+/fwYNjxo6hG43HHsSAfUHefHx8qCILkQfnzZ+3aPFCtsPo0aPgm8Bk4QJOEoHQp29vHngQDtzL66GsnMwK0xU1NTWtlNsGk5OTCyjXN758/UIkEuGVzMzMpqam4uJiqPSMjIzc3Fx4NykpCa3MKZiIlgfh7JSTlx07bizdaLz0ILmRlBRDbwL6QWABaCFUkYXFgyI1LgbBOV5xhPrascMKm2EbymHzls0LF5ls327Z3NysqaWZmJgIxzJ4yKC8vLzLly+NHz9ugcn8/gP6QzTYUFAcVlRUxMUsIbiCCHlw/IRxcBZC/8XT04NuNF56EHoQ0H8ZNGggZMzS0pL28QPkQVbpbA9CHR07fgwkCH/blliCY1dWUWorASoPOjjYL1q0EFuvHbsKbDzF+OnTJ9zKEoJbiIQHw8LCNm3etH79umPHjkZHRzPyWmd7EEZMN2/exG61raiogPZ/4YLdy5cv6T6DhTzIKp3qwfr6+m3btkrLSDk5OXX8UQu216xds2z5shLK5Fq0HrTcbgmv79mz287uPGwsXbrE05PTZ40QXEckPIgT9FwdfkTKg3V1dcuXL5OTl3348CHdd3ft3mVsbAyHgDwopCAPtoM8iB/R8SAc3YyZM3r07B78PJjRmQC9RU1NDRCf/ki9yMjI2traPn37IA8KEciD7SAP4kdEPJibmzt6zOiBgwbExcXRPQ1AeRcuXrS3t584aSLWMZwy1XjdurUDBw2EzyIPCgvIg+0gD+IHvwfBSqamK+bMmQ0DRroRmHgwMzPj3r27bc+DR8dE3713Fwu0F1W57sGMjAxtHS01ddXU1FRGcZqamkJDX3h5PSwpKWmlTLjg4eHx4UP8q1dhNTU1kH/seTs49vT0z62UicjQWiUCCPJgO8iD+MHpQScnJ3EJsd59eoGhaO8NwqDrQRKJtHfvHjl52bb16oCVK83gX0gQAu0sXlz3oJGR4ahRI799+8Z2CghhoUt5EL6Eo96+ZTv8GxoqJy/HFQ+am5vf4QzoiQi7B4uKisCAikqK+QXMnjyj60Ho7sEQ0sLCvKMHDY0Mp0ydkkiB9klErnsQToDy8nK2P44QIrqUB7kSuOJBeXk5UAAnQUJSXNg9+PTpUyjPQ4cOMU+K0bi4sbGx43zU8C8MUefPn8doPXi+z0eNEF66lAe/ff/2kwOysrK6de/GFQ/ev3+viTOg4yPsHrS3t4dKgb4t86RwzssPXTNVNRVpGSlJKYnTZ04L4Lz8COGlS3kQXR/kGXg86OjoCJXi6nqTeVL41yeBCvr06ZOGhrqMrHRFRQVVZORBBNsgD7aDPIgfPB6EnEOlbN26lSvrdraxe89uSDaDZso/5EEE2yAPtoM8iB88HiwrKxs0eCBE8PD0gMJktJgvTg9WVRFyc3O/fPkCsuvTtzdtasiDCLZBHmwHeRA/OO+befTokaycDLbYJkiNbhycHnzw4IGcvCwEGVmZu3fd0fVBBBdBHmwHeRA/+O+jzsnJuXfvnofHfdorehhMPFheXu7j45OQQL4VGXqX/v7+9+/fz87OFsB1OxFCjQh5sKmpKSYm2tfXl9GdsZ3qQXi3oKAApNDxQQgCoTIvL4+u3bqMB/+IID9XhxARRMWD0FbnzZ8rLiEG0U6fPk03Tqd6cNXqVd26d4Nh3YwZM7B5jENevBgydDB4ZIv5FtqnI5AHWQV5EME2IuFBiGO53ZL82+W2rVFRUYwW1ulUD9644XLrlpuZmSlkw8npWmNjo7KKkraO9voN68XE/woODqaKjzzIKsiDCLYRCQ8SCIS+/fooqyhjc6kzggfXB1NSUiQkxffu2xMbGwv6O2V7Kjk5GXJubb2fKibyIKsgDyLYRiQ8iLlm1aqVzJPigQd9fHwgJ25ubt7e3pRnLW6XlpaCEJcuW0oVE3mQVZAHEWwjEh6EsTC8u3nzJuZJ8WBeflBb/wH9ysvL3dxcIUvu7nfKysrAg3PnzaWKLCwehIM9derkhYsX2A4rViyXkZU5e+4sJ4lAUFJWRB5EsIdIeDDrSxa8O3v2LOZJdbYHT58+Ddm4f/9+6+85CFxdb/78+RM2NmzcQBVZWDwIEldVU1HXUGM7DBjYX0xcTE1dlZNEIMjKySAPIthDJDxYV1cHbVVGVjo5+RP2EbrROtWDwcHB4hJiVlZW0CtsamrKysqSlJLYs3dPREQE5Pzq1atU8YXFg3LyshUVFS0c4O7u3rNXT2zZX06YONEIeRDBHiLhQeC6y3XoufTq3dPYeDK2YhwtnedBAoGgpKwEOVRUUlBXV9u0eRNEnjFjunw3ORjN9evXNzc3lyo1YfEguj6I6AKIigebm5s9PT0ochnn6+tDN06nenDjxo2mpiuwcO78OXixsLDQYqvF4sWLoqKiaFNDHmQV5EEE24iKB/GAnqvDD/IgoiuBPNgO8iB+kAcRXQnkwXaQB/GDPIjoSiAPtoM8iB/8HkxNTbW1tbW23v/lyxe6ERh5sKysLDLyTUxMTNtbLS0tCQkJ8R/iSSQSbTrIgwi2QR5sh9qD6QLgQWfnZwFC7MHAwEA5eVlxCTFpGanY2Fi6ceh6kEgkqqiqiIn/BQGKAv6FPe7fv09CUhxSs9hqwYP16hCiQ9fwIOkRxYNfs78WcEBmZma37t1WrVrlfufOy5cv09PTy9nwYA3Zgw6O9l85w9DIcMKE8Tdu3AgMCkpKSioqKq4XNg/C6woKw/r07R0dHY0tPkU3Gl0Pgua8vb3fv3+/fPkyqNng4OC0tDQo2DVrVq9duwZeSU2jXlsdeRDBNl3Eg37+/tA2sPmK2Q6ycuRVwzdt2vTgwYOIiIisrKwKAoFVD1bX1mKrj3Me/p78t7u7+4sXL1JSkotLSuobGoXLg5BzOIpdu3YyT4r59cHHjx9DInfv3b3uch0Tor+/H93ln5AHEWwj9B4EmkjNoAkvby8nJ6fTZ85YW1tbWVlZWFiYm2+BgAcsJnxkx44dN264PHv2LDYmJicnp6q6uomE14NAc0tLbV3dq1evbt68aWd33uaQzc6dO7du3Yo/J78zY25paXnlyhVfX9/IN28yszLLyisaGpvw56SzweNByD82qQTzpJh7EDQKA+FPnz5BYUJqcXFx2BM4x48fo4qJPIhgm67gQeiF1dYRC4uKYOgUGRkZEBgIw2RPD4/7wL17eMP9+56eHvDBwMBASASSKiwqhGRJHaaP/iMwmoO2V1Ja+uVLFgwGQ0JCfHx9HzzwZC0n9+5B1r28vJ48fRoeHp6UlJiXnw9Gxt8z5QF4PHj58mUQ1q1bt5gnxcSD0CXv3qPbvPnzSCQStkxdfHz8mzdvYOPwYerl4ZEHEWzTFTwIvTBok5UEQn5+/ufPaR/i46OioqDX8JpF4CPwQfj458+f8wvyIcGGxsZmmuvxTGihDNKrqmugEWZlZSZ8/Pj+3Ttot6xmBfL+9m1kbGxMSkrK95zvZeXlxPp6lnLS2eDxIHbR9sDBA8yTYuRBIpFoPGVy3359MjMz4d8LF+wgtbdv32LD7X/++YcqPvIggm26ggexC3P1DQ2EqmoYIEPv6fv3b9lkvrIYsr9//w4yhUQI1dXEhgZIltUuGCbl6pqa0rKygh8FOTnf2crJ12/fvuXl5UEnt4JAqCMSWRqe8wA8HiwoKOjZq0f/Af1iYmIqKsrp3uzSyvh3EhgRi4n/Bd3joqKi6upq+HoA/V22v3zm7BlsgEyVDvIggm26ggdbf6uwobGprr6+urYWRpGEqio2AnTlamphNFwPSbEhQSwnzc0tjU1N0IOrrauDBNnLCTi9ugZyQoQ+KWRFcH4hwcB534wdpRMnJS0JNkz69IluHLoeTEtLE5cQAw9C+hCOHj0C3UMDQwNZORk5eVljY+NmmusVyIMItukiHmyltEzoREB3jERqht4T2wH010yZx4nt/ld7Tpo5zQmJkheB6gli4PQgZP7Vq7ADBw7Y2BzMLyigG4euB3/8+HHy5Im28O+/ofAidAxtT9ueO3eutLSUNh3kQQTbdB0PIngJeq4O0ZVAHkSwA/IgoiuBPIhgB+RBRFcCeRDBDoLpQT19PeRBBBsgDyLYQWA96OzsjHmwEHkQgRvkQQQ7tHlQRlb639DQ9xxw9OjRbt27vYmI4CQRQE9/xMiR+jdcXAIDAxMTEgqLCskz9CAPInCAPIhgB/BgQ2Pjs4BnYuJ/cWVSCa4EIyNDbGaK5OTk4hLKDD3IgwgcIA8i2AGb9rGisjIuLjYgIOCO+x0HB4fTp0+fOHHiGHCUt+HYMdivra3tjRs3fP38IiMjMzMzy8rLwdSCdv85QjBBHkSwA3iwiUSqqa39+fNnamrq27eRQUFBPr6+Xt7eD/mBl7eXj49PQGBgxOvXnz4l5eXnCdrMFAhBBnkQwQ7kxwdbWmDgCV3CvPz89PT0jx8/Rr9//+5d1Nuot7wn6l0U7P3Dh/i0tLTc3Jyy8gpifT17T0YiRBDkQQSbYM90E8nTW1QVl5QUFBTk5OZ8J/ON13z/BjvNycnJz88vKi4GNddSZqZAg2IETpAHEeyDqfD3pBLE6tra6pqaqmp+hJoa2HttXV1dfX1DYyNJ8GamQAgyyIMIjviPAoyRmymzQvA3NP+aI+M/NBxGsATyIAKBEHWQBxEIhKiDPIhAIEQd5EEEAiHqIA8iEAhRB3kQgUCIOv8fe5KEO17iZ+sAAAAUdEVYdFNvZnR3YXJlAFlhbmRleC5EaXNrTl/4kQAAAABJRU5ErkJggg=="
    }
   },
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![2023-04-29_17-07-39.png](attachment:2023-04-29_17-07-39.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.groupby('Pclass')['Survived'].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df[['Pclass', 'Survived']].groupby('Pclass', as_index = False).mean()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2. Правда ли, что женщины имеют большие шансы на спасение?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['Sex'].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.groupby('Sex')['Survived'].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df[['Sex', 'Survived']].groupby(['Sex'], as_index=False).mean()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3. Правда ли, что дети имеют большие шансы на спасение?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['IsChild'] = [-1] * df.shape[0] \n",
    "df['IsChild'][df.Age < 20] = 1\n",
    "df['IsChild'][df.Age >= 20] = 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['IsChild'].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df[df['IsChild']!=-1].groupby('IsChild')['Survived'].value_counts(normalize=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 4. Cколько мужчин и женщин в каждом классе (Pclass)?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Воспользуемся функцией для создания таблиц сопряженности. Таблица сопряженности, или перекрестная таблица (cross-tabulation, или для краткости `crosstab`) – это пример сводной таблицы, в которой представлены групповые частоты."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pd.crosstab(df['Pclass'], df['Sex'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 5. Как обращались к мужчинам и женщинам в 1912?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['Title'] = df.Name.str.extract(' ([A-Za-z]+)\\.')\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pd.crosstab(df['Title'], df['Sex'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['Title'] = df['Title'].replace(['Lady', 'Countess','Capt', 'Col', \\\n",
    "'Don', 'Dr', 'Major', 'Rev', 'Sir', 'Jonkheer', 'Dona'], 'Other')\n",
    "\n",
    "df['Title'] = df['Title'].replace('Mlle', 'Miss')\n",
    "df['Title'] = df['Title'].replace('Ms', 'Miss')\n",
    "df['Title'] = df['Title'].replace('Mme', 'Mrs')\n",
    "    \n",
    "df[['Title', 'Survived']].groupby(['Title'], as_index=False).mean()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Корреляции признаков"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Корреляция признаков позволяет оценить наличие линейных(монотонных) зависимостей между данными. Она бывают трех типов:\n",
    "- Положительные значение = Положительные корреляция, т.е. возрастание по одному признаку соответсвует возрастанию по другому признаку и наоборот.\n",
    "- Отрицательные значения = Обратные корреляции, т.е. возрастание по одному признаку, влечет уменьшение другого, и наоборот.\n",
    "- Нулевые занчения =  линейных(монотонных) зависимостей между данными нет."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Если наша задача выявить связь между выжившими и их данными, то нам необходимо фокусироваться на тех признаках, которые имеют сильные положительные и отрицательные корреляции с признаком Survived.\n",
    "\n",
    "Почему? Потому что это означает, что прогнозирование значения Survived имеет прямую зависимость с признакми с положительное корреляцией, и обратную - с отрицательными, т.о. если мы инвертируем обратные значения, то они тоже перейдут в разряд положительных корреляций."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "corr_matrix = df.corr()\n",
    "corr_matrix"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "corr_matrix.style.background_gradient(cmap='coolwarm')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Визуализация"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`Matplotlib` - это базовая библиотека для построения графиков и визуализации данных в Python. Если в `jupyter notebook` выполнить специальную магическую команду `%matplotlib inline`, то графики будут строиться в том же окне браузера. `matplotlib` позволяет строить двумерные графики практически всех нужных типов, с достаточно гибкой регулировкой их параметров; он также поддерживает основные типы трёхмерных графиков, но для серьёзной трёхмерной визуализации данных лучше пользоваться более мощными специализированными системами."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "5KeYf-pJKFRR"
   },
   "source": [
    "Ниже приведены несколько полезных ссылок:\n",
    "\n",
    "[Официальная документация](https://matplotlib.org/stable/)\n",
    "\n",
    "[50 оттенков matplotlib](https://habr.com/ru/post/468295/)\n",
    "\n",
    "[Хороший tutorial](https://devpractice.ru/files/books/python/Matplotlib.book.pdf)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "6EEHh-j1nGrk"
   },
   "source": [
    "У функций в `matplotlib` много параметров.\n",
    "Для того, чтобы посмотреть все параметры, можно воспользоваться справкой, например,\n",
    "\n",
    "`plt.plot?`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#plt.plot?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "uydwARi7PkY_"
   },
   "source": [
    "## Препарируем график"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 555
    },
    "id": "3jaAbCruPFV4",
    "outputId": "a29b21ae-a25f-40fc-a0d4-a51a05031036"
   },
   "outputs": [],
   "source": [
    "from matplotlib.ticker import AutoMinorLocator, MultipleLocator, FuncFormatter\n",
    "\n",
    "\n",
    "np.random.seed(19680801)\n",
    "\n",
    "X = np.linspace(0.5, 3.5, 100)\n",
    "Y1 = 3+np.cos(X)\n",
    "Y2 = 1+np.cos(1+X/0.75)/2\n",
    "Y3 = np.random.uniform(Y1, Y2, len(X))\n",
    "\n",
    "fig = plt.figure(figsize=(8, 8))\n",
    "ax = fig.add_subplot(1, 1, 1, aspect=1)\n",
    "\n",
    "\n",
    "def minor_tick(x, pos):\n",
    "    if not x % 1.0:\n",
    "        return \"\"\n",
    "    return \"%.2f\" % x\n",
    "\n",
    "ax.xaxis.set_major_locator(MultipleLocator(1.000))\n",
    "ax.xaxis.set_minor_locator(AutoMinorLocator(4))\n",
    "ax.yaxis.set_major_locator(MultipleLocator(1.000))\n",
    "ax.yaxis.set_minor_locator(AutoMinorLocator(4))\n",
    "ax.xaxis.set_minor_formatter(FuncFormatter(minor_tick))\n",
    "\n",
    "ax.set_xlim(0, 4)\n",
    "ax.set_ylim(0, 4)\n",
    "\n",
    "ax.tick_params(which='major', width=1.0)\n",
    "ax.tick_params(which='major', length=10)\n",
    "ax.tick_params(which='minor', width=1.0, labelsize=10)\n",
    "ax.tick_params(which='minor', length=5, labelsize=10, labelcolor='0.25')\n",
    "\n",
    "ax.grid(linestyle=\"--\", linewidth=0.5, color='.25', zorder=-10)\n",
    "\n",
    "ax.plot(X, Y1, c=(0.25, 0.25, 1.00), lw=2, label=\"Blue signal\", zorder=10)\n",
    "ax.plot(X, Y2, c=(1.00, 0.25, 0.25), lw=2, label=\"Red signal\")\n",
    "ax.plot(X, Y3, linewidth=0,\n",
    "        marker='o', markerfacecolor='w', markeredgecolor='k')\n",
    "\n",
    "ax.set_title(\"Anatomy of a figure\", fontsize=20, verticalalignment='bottom')\n",
    "ax.set_xlabel(\"X axis label\")\n",
    "ax.set_ylabel(\"Y axis label\")\n",
    "\n",
    "ax.legend( loc='upper right')\n",
    "\n",
    "\n",
    "def circle(x, y, radius=0.15):\n",
    "    from matplotlib.patches import Circle\n",
    "    from matplotlib.patheffects import withStroke\n",
    "    circle = Circle((x, y), radius, clip_on=False, zorder=10, linewidth=1,\n",
    "                    edgecolor='black', facecolor=(0, 0, 0, .0125),\n",
    "                    path_effects=[withStroke(linewidth=5, foreground='w')])\n",
    "    ax.add_artist(circle)\n",
    "\n",
    "\n",
    "def text(x, y, text):\n",
    "    ax.text(x, y, text, backgroundcolor=\"white\",\n",
    "            ha='center', va='top', weight='bold', color='blue')\n",
    "\n",
    "\n",
    "# Minor tick\n",
    "circle(0.50, -0.10)\n",
    "text(0.50, -0.32, \"Minor tick label\")\n",
    "\n",
    "# Major tick\n",
    "circle(-0.03, 4.00)\n",
    "text(0.03, 3.80, \"Major tick\")\n",
    "\n",
    "# Minor tick\n",
    "circle(0.00, 3.50)\n",
    "text(0.00, 3.30, \"Minor tick\")\n",
    "\n",
    "# Major tick label\n",
    "circle(-0.15, 3.00)\n",
    "text(-0.15, 2.80, \"Major tick label\")\n",
    "\n",
    "# X Label\n",
    "circle(1.80, -0.27)\n",
    "text(1.80, -0.45, \"X axis label\")\n",
    "\n",
    "# Y Label\n",
    "circle(-0.27, 1.80)\n",
    "text(-0.27, 1.6, \"Y axis label\")\n",
    "\n",
    "# Title\n",
    "circle(1.60, 4.13)\n",
    "text(1.60, 3.93, \"Title\")\n",
    "\n",
    "# Blue plot\n",
    "circle(1.75, 2.80)\n",
    "text(1.75, 2.60, \"Line\\n(line plot)\")\n",
    "\n",
    "# Red plot\n",
    "circle(1.20, 0.60)\n",
    "text(1.20, 0.40, \"Line\\n(line plot)\")\n",
    "\n",
    "# Scatter plot\n",
    "circle(3.20, 1.75)\n",
    "text(3.20, 1.55, \"Markers\\n(scatter plot)\")\n",
    "\n",
    "# Grid\n",
    "circle(3.00, 3.00)\n",
    "text(3.00, 2.80, \"Grid\")\n",
    "\n",
    "# Legend\n",
    "circle(3.70, 3.80)\n",
    "text(3.70, 3.60, \"Legend\")\n",
    "\n",
    "# Axes\n",
    "circle(0.5, 0.5)\n",
    "text(0.5, 0.3, \"Axes\")\n",
    "\n",
    "# Figure\n",
    "circle(-0.3, 0.65)\n",
    "text(-0.3, 0.45, \"Figure\")\n",
    "\n",
    "color = 'blue'\n",
    "ax.annotate('Spines', xy=(4.0, 0.35), xycoords='data',\n",
    "            xytext=(3.3, 0.5), textcoords='data',\n",
    "            weight='bold', color=color,\n",
    "            arrowprops=dict(arrowstyle='->',\n",
    "                            connectionstyle=\"arc3\",\n",
    "                            color=color))\n",
    "\n",
    "ax.annotate('', xy=(3.15, 0.0), xycoords='data',\n",
    "            xytext=(3.45, 0.45), textcoords='data',\n",
    "            weight='bold', color=color,\n",
    "            arrowprops=dict(arrowstyle='->',\n",
    "                            connectionstyle=\"arc3\",\n",
    "                            color=color))\n",
    "\n",
    "ax.text(4.0, -0.4, \"Made with http://matplotlib.org\",\n",
    "        fontsize=10, ha=\"right\", color='.5')\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "HkGHd2dNnTq9"
   },
   "source": [
    "## Простейший график"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "MPikNsAYtr8F"
   },
   "source": [
    "Благодаря **Numpy** у нас всегда есть материалы в виде массивов чисел. \n",
    "\n",
    "Создадим ряд чисел одно за другим, подобно линии, с помощью команды `np.linspace()`\n",
    "\n",
    "Числа равномерно распределяются в интервале от **0** до **15** (это будут первые два значения в скобках). А всего чисел в ряде будет **100** (третье значение в скобках). Рассмотрим подробнее:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "yLHGPWqFt0OP",
    "outputId": "64c6eb84-bc22-4562-a30b-082197da02ac"
   },
   "outputs": [],
   "source": [
    "x = np.linspace(0, 15, 100)\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Теперь это точки для построения графика синуса (значения по оси x). Для вычисления значений синуса (значений по оси y) вызовем `np.sin(x)`, где **x** – массив значений по горизонтали. При этом получится массив значений синуса, каждое из которых будет вычислено от аргумента на том же месте в массиве **x**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "zOIEgpvSt6o0",
    "outputId": "b7d31a6f-892a-45d4-c8ca-e842d558924b"
   },
   "outputs": [],
   "source": [
    "y = np.sin(x) \n",
    "# Содержимое массива у выглядит так:\n",
    "print(y) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "r0Mq8DWFuBUj"
   },
   "source": [
    "**Как бы вы построили график, если у вас есть точки и для x, и для y?**\n",
    "\n",
    "Наверное, вы бы начертили две пересекающиеся линии, которые перпендикулярны (декартовы оси). Потом отметили место их пересечения как начало отсчета или «ноль». Потом решили, что вертикальная линия – это ваша ось **y**, горизонтальная – ось **x**, и начали бы поочередно наносить точки из массивов **x** и **y**, которые вы уже получили. Так бы получился график `sin(x)`, верно? \n",
    "\n",
    "Теперь это можно сделать за пару действий:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 265
    },
    "id": "FtdY7rl0uFkz",
    "outputId": "f3a6961e-617d-49f8-d509-b40d6c57fe28"
   },
   "outputs": [],
   "source": [
    "plt.plot(x, y)                                # Отрисовка графика командой plot(), в которую переданы массивы точек для x и y\n",
    "plt.show()                                    # С помощью .show() выводится график"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "2CB3L05yuNTj"
   },
   "source": [
    "Если вам необходимо добавить на график подписи, то это в разы легче, чем написать их в тетради.\n",
    "\n",
    "В этом вам помогут дополнительные команды:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 295
    },
    "id": "eftzA3P5uNp7",
    "outputId": "69a8ed4f-7b71-4c73-d047-e04ca83f5e33"
   },
   "outputs": [],
   "source": [
    "plt.plot(x, y)                                # Отрисовка того же графика\n",
    "plt.title(\"y=sin(x)\")                         # Команда .title() - и график подписан указанным в скобках именем\n",
    "plt.xlabel('Переменная X')                    # Команда .xlabel() добавит надпись только для оси x\n",
    "plt.ylabel('Переменная Y')                    # А команда .ylabel() добавит надпись для оси y\n",
    "plt.show()                                    # Фиксация результата и вывод - командой .show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "dPTnglGfuely"
   },
   "source": [
    "Также вы можете сделать график удобного для вас размера. Пространство, где он рисуется, называется полотном графика. Для указания размера полотна используйте команду `.figure()`. Не забудьте указать в скобках слово-параметр **figsize=** и в кортеже сами размеры для вашего графика:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 53
    },
    "id": "hZs7t5SUuirA",
    "outputId": "c8715195-a0ac-43e4-d25b-040b0ab10d6a"
   },
   "outputs": [],
   "source": [
    "plt.figure(figsize=(10, 5))                   # И вот - размер полотна в дюймах указан\n",
    "                                              # Первое число 10 - по оси x, второе число 5 - по оси y "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "qQAbNF5eul2C"
   },
   "source": [
    "Несложно нарисовать и больше одного графика на одном и том же полотне. У вас часто будет возникать такая необходимость. Для этого продолжайте использовать команду `.plot()`. Не забудьте указать слегка видоизмененные данные, чтобы графики не перекрывали друг друга. Здесь используем обычную функцию из значений `cos(x)/2`, которая имеется в **Numpy**:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 283
    },
    "id": "UKjOtTp8uoCC",
    "outputId": "5381d82e-31b6-413a-a6fe-f9fb0e769b4b"
   },
   "outputs": [],
   "source": [
    "plt.plot(x, y, label='sin(x)')                # Параметр label поможет подписать кривую графика (см. далее)\n",
    "plt.plot(x, np.cos(x)/2, label='cos(x)/2')    # А так добавляется еще один график на полотно"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 350
    },
    "id": "b8rakqkrutsV",
    "outputId": "4e3cc3ad-5b5e-42c8-e027-557d56a9c33b"
   },
   "outputs": [],
   "source": [
    "plt.figure(figsize=(10, 5))                   # Здесь задаётся размер полотна в дюймах\n",
    "                                              # по оси x и y соответственно\n",
    "\n",
    "plt.plot(x, y, label='sin(x)')                # Эта команда строит график, а параметр label задает подпись кривой\n",
    "plt.plot(x, np.cos(x)/2, label='cos(x)/2')    # Эта команда строит еще один график cos(x) на полотне\n",
    "\n",
    "plt.title(\"y = sin(x)\")                       # Заголовок графика\n",
    "plt.xlabel('Переменная X')                    # Надпись для оси x\n",
    "plt.ylabel('Переменная Y')                    # Надпись для оси y\n",
    "\n",
    "plt.legend()                                  # команда для \"легенды\" - legend()\n",
    "                                              # Она позволяет отобразить подписи кривых, указанные в .plot(label=)\n",
    "\n",
    "plt.grid()                                    # команда grid(), чтобы отрисовать сетку на фоне\n",
    "\n",
    "plt.show()                                    # Команда для воплощения графика в жизнь "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ftoQBGIwvEjD"
   },
   "source": [
    "А теперь красивый график"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 458
    },
    "id": "3tUA3-IzvH7L",
    "outputId": "0d87af37-088c-4492-e4b3-50e539712ae0"
   },
   "outputs": [],
   "source": [
    "plt.figure(figsize=(14, 7))                   # Задание размера полотна в дюймах\n",
    "\n",
    "plt.plot(x,y , label='sin(x)', color='#4b0082', linewidth=4,\n",
    "         marker='h', markerfacecolor='lightgreen', markeredgewidth=2,\n",
    "         markersize=10, markevery=5)\n",
    "\n",
    "plt.plot(x, np.cos(x)/2, label='cos(x)/2', linewidth=3, color='lightcoral',\n",
    "         marker='D', markeredgecolor='black', markevery=5)\n",
    "\n",
    "plt.title('y = sin(x)')                       # Заголовок графика\n",
    "plt.xlabel('Переменная X')                    # Надпись для оси x\n",
    "plt.ylabel('Переменная Y')                    # Надпись для оси y\n",
    "\n",
    "plt.legend()                                  # Отрисовка названий графиков (\"легенды\")\n",
    "\n",
    "plt.grid()                                    # Отрисовка сетки\n",
    "\n",
    "plt.show()                                    # Вывод графика"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "_Wa_nH64vOn0"
   },
   "source": [
    "Некоторые параметры, которые использовались выше в скобках команд:\n",
    "- **marker** – тип маркера;\n",
    "- **color** – цвет линии;\n",
    "- **mec** – цвет маркера;\n",
    "- **linestyle** – стиль линии;\n",
    "- **label** – подпись кривой графика;\n",
    "- **linewidth** – ширина линии;\n",
    "- **markersize** – размер маркера.\n",
    "\n",
    "Другие команды вы найдете в полном описании документации **Matplotlib**. Описанные там элементы стиля дают возможность существенно улучшить наглядность графика.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "hU4D7j681FK5"
   },
   "source": [
    "# Визуальный анализ данных"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "xU-dSMX51ofj"
   },
   "source": [
    "Давайте на практике остроим разные графики разведочного анализа данных для набора Титаника."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 250
    },
    "id": "S5XDKFrq2azJ",
    "outputId": "9d3cf9c6-4324-4528-c76c-35b0bdec6575"
   },
   "outputs": [],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Визуализируем пропуски"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#!pip install missingno #установка новой библиотеки\n",
    "import missingno #подключение новой библиотеки\n",
    "missingno.matrix(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "vODuCpN62kqS"
   },
   "source": [
    "### Сколько выживших?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 495
    },
    "id": "1WHf3x2Q2f9D",
    "outputId": "485e190f-8009-4262-962b-f4f76b71b35d"
   },
   "outputs": [],
   "source": [
    "f, ax=plt.subplots(1,2,figsize=(18,8)) # одна строка и два столбца графиков\n",
    "df['Survived'].value_counts().plot.pie(explode=[0,0.2],autopct='%1.1f%%',ax=ax[0],shadow=True)\n",
    "ax[0].set_title('Выжившие')\n",
    "ax[0].set_ylabel('')\n",
    "df['Survived'].value_counts().plot.bar(ax=ax[1])\n",
    "ax[1].set_title('Выжившие')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "5c_p4wz24OrK"
   },
   "source": [
    "### Категориальные переменные"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "CFTtUh1j4s85"
   },
   "source": [
    "Категориальные переменные - переменные, значения которых являются некоторыми категориями. К примеру, пол - это категориальная переменная, которая имеет два возможных значения (мужчина и женщина). Такие переменные не нельзя отсортировать или задать для них порядок. Ещё такие признаки называют качественными."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Столбчатая диаграмма** - методы `plot.bar()` и `plot.barh()` строят вертикальные и горизонтальные столбчатые диаграммы. В этом случае индексы объектов `Series` и `DataFrame` используются в качестве меток на оси `x` (`bar`) или `y` (`barh`)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "2VoRZCVx2f_x"
   },
   "outputs": [],
   "source": [
    "def bar_plot(variable):\n",
    " \n",
    "    # получаем переменные\n",
    "    var = df[variable]\n",
    "    # считаем количество значений для категириальной переменной\n",
    "    varValue = var.value_counts()\n",
    "    \n",
    "    # визуализируем\n",
    "    plt.figure(figsize = (10,5))\n",
    "    plt.bar(varValue.index, varValue)\n",
    "    plt.xticks(varValue.index, varValue.index.values)\n",
    "    plt.ylabel(\"Частота\")\n",
    "    plt.title(variable)\n",
    "    plt.show()\n",
    "    print(\"{}: \\n {}\".format(variable, varValue))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 1000
    },
    "id": "kcoSWBhB2gCc",
    "outputId": "52d58e15-5a4e-4855-c2d4-ac2aab8f54e4",
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "category = [\"Survived\",\"Sex\",\"Pclass\",\"Embarked\",\"SibSp\", \"Parch\"]\n",
    "for c in category:\n",
    "    bar_plot(c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "yPldeoC1_i9E"
   },
   "source": [
    "### Пол"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "bFnTmOJx6z59",
    "outputId": "24700b38-4479-47e9-84f5-e63b64f01e6f"
   },
   "outputs": [],
   "source": [
    "df.groupby(['Sex','Survived'])['Survived'].count()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 548
    },
    "id": "riVwGoH06z8q",
    "outputId": "30ba5503-15b6-4767-b053-7f982d5330eb"
   },
   "outputs": [],
   "source": [
    "f,ax=plt.subplots(1,2,figsize=(18,8))\n",
    "df[['Sex','Survived']].groupby(['Sex']).mean().plot.bar(ax=ax[0])\n",
    "ax[0].set_title('Survived vs Sex')\n",
    "sns.countplot(x=df['Sex'], hue=df['Survived'], ax=ax[1])\n",
    "ax[1].set_title('Распределение выживших по полу')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "xP8YZdWc_96U"
   },
   "source": [
    "Мужчин на борту было ощутимо больше чем женщин. И всё же количество спасшихся женщин почти в двое больше спасшихся мужчин. Процент выживаемости для женщин около 75%, в то время как для мужчин он составляет примерно 18-19%."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "t1lr-1S8AGKB"
   },
   "source": [
    "### Pclass "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 206
    },
    "id": "pfPWRwSS6z_j",
    "outputId": "38750a29-c40d-4921-c171-1b0ce3a7a553"
   },
   "outputs": [],
   "source": [
    "pd.crosstab(df.Pclass,df.Survived,margins=True).style.background_gradient(cmap='summer_r')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 513
    },
    "id": "38SjQfp960B1",
    "outputId": "8b2fe0aa-45ba-48f8-e809-906b57771b9d"
   },
   "outputs": [],
   "source": [
    "f,ax=plt.subplots(1,2,figsize=(18,8))\n",
    "df['Pclass'].value_counts().plot.bar(color=['#CD7F32','#FFDF00','#D3D3D3'],ax=ax[0])\n",
    "ax[0].set_title('Количество пассажиров различных классов')\n",
    "ax[0].set_ylabel('Количество')\n",
    "sns.countplot(x=df['Pclass'],hue=df['Survived'],ax=ax[1])\n",
    "ax[1].set_title('Распределение выживших по классу')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "AgzJ_EuwAnTX"
   },
   "source": [
    "Но как мы видим у пассажиров первого класса было на много больше шансов на спасение. Хотя в третьем классе и было куда больше пассажиров выживших среди них не много, спаслись примерно 25%. Из пассажиров первого класса спаслись примерно 63%, из пассажиров второго класса примерно 48%."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "U5eBWOVb5sjR"
   },
   "source": [
    "## Числовые переменные"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Гистограмма плотности распределения** — это столбиковая диаграмма, которая показывает, как данные распределяются по группам значений. Собранные данные представляют в виде ряда прямоугольников, одинаковых по ширине и различающихся по высоте. Анализ характера изменения высот позволяет оценить динамику процесса.\n",
    "\n",
    "Ось Y показывает с какой вероятностью случайно выбранное значение из ряда будет принадлежать определенному интервалу."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "gVKqHOfB2gHP"
   },
   "outputs": [],
   "source": [
    "def plot_hist(variable):\n",
    "    plt.figure(figsize = (10,5))\n",
    "    plt.hist(df[variable], bins = 50, color='green', density=True)\n",
    "    plt.xlabel(variable)\n",
    "    plt.ylabel(\"Частота\")\n",
    "    plt.title(\"Распределение переменной {}\".format(variable))\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 1000
    },
    "id": "R5Rvf9ZJ55-Q",
    "outputId": "9970c01f-63d5-4659-a19b-da96195de0b6"
   },
   "outputs": [],
   "source": [
    "numeric = [\"Fare\", \"Age\",\"PassengerId\"]\n",
    "for n in numeric:\n",
    "    plot_hist(n)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "1z0Bb7HLD19q"
   },
   "source": [
    "**Диаграмма рассеяния** - еще один часто используемый тип графика является простой точечный график, близкий родственник линейного графика. Вместо того, чтобы точки соединялись отрезками линий, здесь точки представлены по отдельности точкой, кругом или другой формой. Позволяет построить распределение двух колонок данных и визуально обнаружить наличие зависимости. Не предполагается, что значения упорядочены (например, по времени).\n",
    "\n",
    "Построим график зависмости стоимости билета от возраста. Можно ли увидеть какую-либо зависимость?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 388
    },
    "id": "i0nty7h0D1Tg",
    "outputId": "a70cfc14-c3d1-47ff-8cf2-1135341c0ce8"
   },
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(figsize=(10, 6))\n",
    "ax.scatter(x = df['Age'], y = df['Fare'])\n",
    "plt.xlabel(\"Возраст\")\n",
    "plt.ylabel(\"Цена билета\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(figsize=(10, 5))\n",
    "\n",
    "ax.scatter(df[df[\"Survived\"]==1][\"Age\"], df[df[\"Survived\"]==1][\"Fare\"], c=\"blue\", alpha=0.5)\n",
    "ax.scatter(df[df[\"Survived\"]==0][\"Age\"], df[df[\"Survived\"]==0][\"Fare\"], c=\"green\", alpha=0.5)\n",
    "\n",
    "ax.set_xlabel(\"Возраст\")\n",
    "ax.set_ylabel(\"Цена билета\")\n",
    "\n",
    "\n",
    "ax.legend(handles=color_patches)\n",
    "\n",
    "fig.suptitle(\"Выживаемость пассажиров в зависимости от возраста и стоимости билета\");"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Me4rUE9rCBhO"
   },
   "source": [
    "[**Box plot**](https://ru.wikipedia.org/wiki/Ящик_с_усами) &mdash; график, использующийся в описательной статистике, компактно изображающий одномерное распределение вероятностей.\n",
    "\n",
    "Такой вид диаграммы в удобной форме показывает медиану (или, если нужно, среднее), нижний и верхний квартили, минимальное и максимальное значение выборки и выбросы. Несколько таких ящиков можно нарисовать бок о бок, чтобы визуально сравнивать одно распределение с другим; их можно располагать как горизонтально, так и вертикально. Расстояния между различными частями ящика позволяют определить степень разброса (дисперсии) и асимметрии данных и выявить выбросы."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 513
    },
    "id": "GGmFmQxy6ViS",
    "outputId": "db042fb3-d075-4e41-e5d1-639143e297a2"
   },
   "outputs": [],
   "source": [
    "f,ax=plt.subplots(1,2,figsize=(18,8))\n",
    "sns.boxplot(x = 'Pclass', y = 'Age', hue = 'Survived', data = df, palette = 'flare', ax=ax[0])\n",
    "ax[0].set_title('Pclass and Age vs Survived')\n",
    "ax[0].set_yticks(range(0,110,10))\n",
    "sns.boxplot(x = 'Sex', y = 'Age', hue = 'Survived', data = df, ax=ax[1])\n",
    "ax[1].set_title('Sex and Age vs Survived')\n",
    "ax[1].set_yticks(range(0,110,10))\n",
    "plt.show()\n",
    "f.savefig('saved_figure-100pi.png', dpi = 100) # сохранение графика"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "8pZp7-7fCcuS"
   },
   "source": [
    "1) Число детей увеличивается с классом и показатель выживаемости для пассажиров младше 10 лет (т. е. детей) выглядит неплохим не зависимо от класса.\n",
    "\n",
    "2) Шансы выжить для пассажиров в возрасте от 20 до 50 лет из первого класса довольно высокие и ещё выше для женщин.\n",
    "\n",
    "3) Для мужчин шанс выжить понижается с повышением возраста."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Тепловая карта корреляций"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(15,6))\n",
    "sns.heatmap(df.corr(), vmax=0.6, square=True, annot=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Парные диаграммы"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Комбинация гистограмм и диаграмм рассеивания для всего набора данных. Выводится матрица графиков. На пересечении строки и столбца, которые соответствуют двум показателям, строится диаграмма рассеивания. В главной диагонали матрицы строятся гистограммы распределения соответствующих показателей."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sns.pairplot(df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "colab": {
   "provenance": [],
   "toc_visible": true
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
